190d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen"""
254e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny ChenTest the lldb disassemble command on lib stdc++.
390d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen"""
490d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen
590d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chenimport os, time
690d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chenimport unittest2
790d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chenimport lldb
890d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chenfrom lldbtest import *
9431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Inghamimport lldbutil
1090d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen
1190d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chenclass StdCXXDisassembleTestCase(TestBase):
1290d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen
13b26db29eebfbc2dc88776afa738a9b6a8fcc8f75Johnny Chen    mydir = os.path.join("lang", "cpp", "stl")
1490d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen
1545ac7ac0a0cea43c3874d986da8b107695d630c1Johnny Chen    def setUp(self):
160910eb32b94bd67b0357d34d0951aad197742569Johnny Chen        # Call super's setUp().
170910eb32b94bd67b0357d34d0951aad197742569Johnny Chen        TestBase.setUp(self)
1845ac7ac0a0cea43c3874d986da8b107695d630c1Johnny Chen        # Find the line number to break inside main().
1945ac7ac0a0cea43c3874d986da8b107695d630c1Johnny Chen        self.line = line_number('main.cpp', '// Set break point at this line.')
2045ac7ac0a0cea43c3874d986da8b107695d630c1Johnny Chen
2154e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen    # rdar://problem/8504895
2254e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen    # Crash while doing 'disassemble -n "-[NSNumber descriptionWithLocale:]"
2390d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen    @unittest2.skipIf(TestBase.skipLongRunningTest(), "Skip this long running test")
2490d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen    def test_stdcxx_disasm(self):
2590d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen        """Do 'disassemble' on each and every 'Code' symbol entry from the std c++ lib."""
2690d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen        self.buildDefault()
2790d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen        exe = os.path.join(os.getcwd(), "a.out")
2890d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
2990d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen
3045ac7ac0a0cea43c3874d986da8b107695d630c1Johnny Chen        # rdar://problem/8543077
3145ac7ac0a0cea43c3874d986da8b107695d630c1Johnny Chen        # test/stl: clang built binaries results in the breakpoint locations = 3,
3245ac7ac0a0cea43c3874d986da8b107695d630c1Johnny Chen        # is this a problem with clang generated debug info?
3345ac7ac0a0cea43c3874d986da8b107695d630c1Johnny Chen        #
3490d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen        # Break on line 13 of main.cpp.
35431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True)
3690d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen
3790d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen        self.runCmd("run", RUN_SUCCEEDED)
3890d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen
3990d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen        # Now let's get the target as well as the process objects.
4090d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen        target = self.dbg.GetSelectedTarget()
4190d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen        process = target.GetProcess()
4290d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen
438a87d5244a61570e06f9b48b9bc04773e82e301eJohnny Chen        # The process should be in a 'stopped' state.
440a19a1b9c25117854f226256805239d95153ed2dGreg Clayton        self.expect(str(process), STOPPED_DUE_TO_BREAKPOINT, exe=False,
4590d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen            substrs = ["a.out",
468a87d5244a61570e06f9b48b9bc04773e82e301eJohnny Chen                       "stopped"])
4790d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen
4854e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        # Disassemble the functions on the call stack.
4954e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        self.runCmd("thread backtrace")
5054e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        thread = process.GetThreadAtIndex(0)
5154e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        depth = thread.GetNumFrames()
5254e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        for i in range(depth - 1):
5354e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen            frame = thread.GetFrameAtIndex(i)
5454e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen            function = frame.GetFunction()
5554e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen            self.runCmd("disassemble -n '%s'" % function.GetName())
5654e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen
5790d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen        # Iterate through the available modules, looking for stdc++ library...
5890d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen        for i in range(target.GetNumModules()):
5990d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen            module = target.GetModuleAtIndex(i)
6090d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen            fs = module.GetFileSpec()
6190d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen            if (fs.GetFilename().startswith("libstdc++")):
620a19a1b9c25117854f226256805239d95153ed2dGreg Clayton                lib_stdcxx = str(fs)
6390d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen                break
6490d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen
6590d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen        # At this point, lib_stdcxx is the full path to the stdc++ library and
6690d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen        # module is the corresponding SBModule.
6790d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen
6890d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen        self.expect(fs.GetFilename(), "Libraray StdC++ is located", exe=False,
6990d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen            substrs = ["libstdc++"])
7090d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen
710a19a1b9c25117854f226256805239d95153ed2dGreg Clayton        self.runCmd("image dump symtab %s" % str(fs))
7254e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        raw_output = self.res.GetOutput()
7354e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        # Now, look for every 'Code' symbol and feed its load address into the
7454e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        # command: 'disassemble -s load_address -e end_address', where the
7554e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        # end_address is taken from the next consecutive 'Code' symbol entry's
7654e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        # load address.
7754e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        #
7854e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        # The load address column comes after the file address column, with both
7954e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        # looks like '0xhhhhhhhh', i.e., 8 hexadecimal digits.
8054e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        codeRE = re.compile(r"""
8154e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen                             \ Code\ {9}      # ' Code' followed by 9 SPCs,
8254e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen                             0x[0-9a-f]{16}   # the file address column, and
8354e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen                             \                # a SPC, and
8454e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen                             (0x[0-9a-f]{16}) # the load address column, and
8554e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen                             .*               # the rest.
8654e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen                             """, re.VERBOSE)
8754e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        # Maintain a start address variable; if we arrive at a consecutive Code
8854e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        # entry, then the load address of the that entry is fed as the end
8954e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        # address to the 'disassemble -s SA -e LA' command.
9054e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        SA = None
9154e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen        for line in raw_output.split(os.linesep):
9254e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen            match = codeRE.search(line)
9354e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen            if match:
9454e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen                LA = match.group(1)
95df18b15f8693be6c876a9d34bf2cec5f3a4f7111Johnny Chen                if self.TraceOn():
96df18b15f8693be6c876a9d34bf2cec5f3a4f7111Johnny Chen                    print "line:", line
97df18b15f8693be6c876a9d34bf2cec5f3a4f7111Johnny Chen                    print "load address:", LA
98df18b15f8693be6c876a9d34bf2cec5f3a4f7111Johnny Chen                    print "SA:", SA
9954e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen                if SA and LA:
100df18b15f8693be6c876a9d34bf2cec5f3a4f7111Johnny Chen                    if int(LA, 16) > int(SA, 16):
101df18b15f8693be6c876a9d34bf2cec5f3a4f7111Johnny Chen                        self.runCmd("disassemble -s %s -e %s" % (SA, LA))
10254e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen                SA = LA
10354e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen            else:
10454e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen                # This entry is not a Code entry.  Reset SA = None.
10554e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen                SA = None
10654e1ea473d083dc3d2b4a0363448f45f9faabea0Johnny Chen
10790d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen
10890d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chenif __name__ == '__main__':
10990d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen    import atexit
11090d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen    lldb.SBDebugger.Initialize()
11190d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen    atexit.register(lambda: lldb.SBDebugger.Terminate())
11290d73bc3549f1b1c64446bb3b43f5676e52ee707Johnny Chen    unittest2.main()
113