Home | History | Annotate | Download | only in stl
      1 """
      2 Test the lldb disassemble command on lib stdc++.
      3 """
      4 
      5 import os, time
      6 import unittest2
      7 import lldb
      8 from lldbtest import *
      9 import lldbutil
     10 
     11 class StdCXXDisassembleTestCase(TestBase):
     12 
     13     mydir = os.path.join("lang", "cpp", "stl")
     14 
     15     def setUp(self):
     16         # Call super's setUp().
     17         TestBase.setUp(self)
     18         # Find the line number to break inside main().
     19         self.line = line_number('main.cpp', '// Set break point at this line.')
     20 
     21     # rdar://problem/8504895
     22     # Crash while doing 'disassemble -n "-[NSNumber descriptionWithLocale:]"
     23     @unittest2.skipIf(TestBase.skipLongRunningTest(), "Skip this long running test")
     24     def test_stdcxx_disasm(self):
     25         """Do 'disassemble' on each and every 'Code' symbol entry from the std c++ lib."""
     26         self.buildDefault()
     27         exe = os.path.join(os.getcwd(), "a.out")
     28         self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
     29 
     30         # rdar://problem/8543077
     31         # test/stl: clang built binaries results in the breakpoint locations = 3,
     32         # is this a problem with clang generated debug info?
     33         #
     34         # Break on line 13 of main.cpp.
     35         lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True)
     36 
     37         self.runCmd("run", RUN_SUCCEEDED)
     38 
     39         # Now let's get the target as well as the process objects.
     40         target = self.dbg.GetSelectedTarget()
     41         process = target.GetProcess()
     42 
     43         # The process should be in a 'stopped' state.
     44         self.expect(str(process), STOPPED_DUE_TO_BREAKPOINT, exe=False,
     45             substrs = ["a.out",
     46                        "stopped"])
     47 
     48         # Disassemble the functions on the call stack.
     49         self.runCmd("thread backtrace")
     50         thread = process.GetThreadAtIndex(0)
     51         depth = thread.GetNumFrames()
     52         for i in range(depth - 1):
     53             frame = thread.GetFrameAtIndex(i)
     54             function = frame.GetFunction()
     55             self.runCmd("disassemble -n '%s'" % function.GetName())
     56 
     57         # Iterate through the available modules, looking for stdc++ library...
     58         for i in range(target.GetNumModules()):
     59             module = target.GetModuleAtIndex(i)
     60             fs = module.GetFileSpec()
     61             if (fs.GetFilename().startswith("libstdc++")):
     62                 lib_stdcxx = str(fs)
     63                 break
     64 
     65         # At this point, lib_stdcxx is the full path to the stdc++ library and
     66         # module is the corresponding SBModule.
     67 
     68         self.expect(fs.GetFilename(), "Libraray StdC++ is located", exe=False,
     69             substrs = ["libstdc++"])
     70 
     71         self.runCmd("image dump symtab %s" % str(fs))
     72         raw_output = self.res.GetOutput()
     73         # Now, look for every 'Code' symbol and feed its load address into the
     74         # command: 'disassemble -s load_address -e end_address', where the
     75         # end_address is taken from the next consecutive 'Code' symbol entry's
     76         # load address.
     77         #
     78         # The load address column comes after the file address column, with both
     79         # looks like '0xhhhhhhhh', i.e., 8 hexadecimal digits.
     80         codeRE = re.compile(r"""
     81                              \ Code\ {9}      # ' Code' followed by 9 SPCs,
     82                              0x[0-9a-f]{16}   # the file address column, and
     83                              \                # a SPC, and
     84                              (0x[0-9a-f]{16}) # the load address column, and
     85                              .*               # the rest.
     86                              """, re.VERBOSE)
     87         # Maintain a start address variable; if we arrive at a consecutive Code
     88         # entry, then the load address of the that entry is fed as the end
     89         # address to the 'disassemble -s SA -e LA' command.
     90         SA = None
     91         for line in raw_output.split(os.linesep):
     92             match = codeRE.search(line)
     93             if match:
     94                 LA = match.group(1)
     95                 if self.TraceOn():
     96                     print "line:", line
     97                     print "load address:", LA
     98                     print "SA:", SA
     99                 if SA and LA:
    100                     if int(LA, 16) > int(SA, 16):
    101                         self.runCmd("disassemble -s %s -e %s" % (SA, LA))
    102                 SA = LA
    103             else:
    104                 # This entry is not a Code entry.  Reset SA = None.
    105                 SA = None
    106 
    107 
    108 if __name__ == '__main__':
    109     import atexit
    110     lldb.SBDebugger.Initialize()
    111     atexit.register(lambda: lldb.SBDebugger.Terminate())
    112     unittest2.main()
    113