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