xref: /llvm-project/lldb/scripts/android/host_art_bt.py (revision 602e47c5f9fd2e14c7bfb6111e6558fa0d27c87f)
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