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