Home | History | Annotate | Download | only in target
      1 """
      2 Test SBTarget APIs.
      3 """
      4 
      5 import os, time
      6 import re
      7 import unittest2
      8 import lldb, lldbutil
      9 from lldbtest import *
     10 
     11 class TargetAPITestCase(TestBase):
     12 
     13     mydir = os.path.join("python_api", "target")
     14 
     15     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     16     @python_api_test
     17     @dsym_test
     18     def test_find_global_variables_with_dsym(self):
     19         """Exercise SBTaget.FindGlobalVariables() API."""
     20         d = {'EXE': 'a.out'}
     21         self.buildDsym(dictionary=d)
     22         self.setTearDownCleanup(dictionary=d)
     23         self.find_global_variables('a.out')
     24 
     25     #rdar://problem/9700873
     26     # Find global variable value fails for dwarf if inferior not started
     27     # (Was CrashTracer: [USER] 1 crash in Python at _lldb.so: lldb_private::MemoryCache::Read + 94)
     28     #
     29     # It does not segfaults now.  But for dwarf, the variable value is None if
     30     # the inferior process does not exist yet.  The radar has been updated.
     31     #@unittest232.skip("segmentation fault -- skipping")
     32     @python_api_test
     33     @dwarf_test
     34     def test_find_global_variables_with_dwarf(self):
     35         """Exercise SBTarget.FindGlobalVariables() API."""
     36         d = {'EXE': 'b.out'}
     37         self.buildDwarf(dictionary=d)
     38         self.setTearDownCleanup(dictionary=d)
     39         self.find_global_variables('b.out')
     40 
     41     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     42     @python_api_test
     43     @dsym_test
     44     def test_find_functions_with_dsym(self):
     45         """Exercise SBTaget.FindFunctions() API."""
     46         d = {'EXE': 'a.out'}
     47         self.buildDsym(dictionary=d)
     48         self.setTearDownCleanup(dictionary=d)
     49         self.find_functions('a.out')
     50 
     51     @python_api_test
     52     @dwarf_test
     53     def test_find_functions_with_dwarf(self):
     54         """Exercise SBTarget.FindFunctions() API."""
     55         d = {'EXE': 'b.out'}
     56         self.buildDwarf(dictionary=d)
     57         self.setTearDownCleanup(dictionary=d)
     58         self.find_functions('b.out')
     59 
     60     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     61     @python_api_test
     62     @dsym_test
     63     def test_get_description_with_dsym(self):
     64         """Exercise SBTaget.GetDescription() API."""
     65         self.buildDsym()
     66         self.get_description()
     67 
     68     @python_api_test
     69     @dwarf_test
     70     def test_get_description_with_dwarf(self):
     71         """Exercise SBTarget.GetDescription() API."""
     72         self.buildDwarf()
     73         self.get_description()
     74 
     75     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     76     @python_api_test
     77     @dsym_test
     78     def test_launch_new_process_and_redirect_stdout_with_dsym(self):
     79         """Exercise SBTaget.Launch() API."""
     80         self.buildDsym()
     81         self.launch_new_process_and_redirect_stdout()
     82 
     83     @python_api_test
     84     @dwarf_test
     85     def test_launch_new_process_and_redirect_stdout_with_dwarf(self):
     86         """Exercise SBTarget.Launch() API."""
     87         self.buildDwarf()
     88         self.launch_new_process_and_redirect_stdout()
     89 
     90     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     91     @python_api_test
     92     @dsym_test
     93     def test_resolve_symbol_context_with_address_with_dsym(self):
     94         """Exercise SBTaget.ResolveSymbolContextForAddress() API."""
     95         self.buildDsym()
     96         self.resolve_symbol_context_with_address()
     97 
     98     @python_api_test
     99     @dwarf_test
    100     def test_resolve_symbol_context_with_address_with_dwarf(self):
    101         """Exercise SBTarget.ResolveSymbolContextForAddress() API."""
    102         self.buildDwarf()
    103         self.resolve_symbol_context_with_address()
    104 
    105     def setUp(self):
    106         # Call super's setUp().
    107         TestBase.setUp(self)
    108         # Find the line number to of function 'c'.
    109         self.line1 = line_number('main.c', '// Find the line number for breakpoint 1 here.')
    110         self.line2 = line_number('main.c', '// Find the line number for breakpoint 2 here.')
    111 
    112     def find_global_variables(self, exe_name):
    113         """Exercise SBTaget.FindGlobalVariables() API."""
    114         exe = os.path.join(os.getcwd(), exe_name)
    115 
    116         # Create a target by the debugger.
    117         target = self.dbg.CreateTarget(exe)
    118         self.assertTrue(target, VALID_TARGET)
    119 
    120         #rdar://problem/9700873
    121         # Find global variable value fails for dwarf if inferior not started
    122         # (Was CrashTracer: [USER] 1 crash in Python at _lldb.so: lldb_private::MemoryCache::Read + 94)
    123         #
    124         # Remove the lines to create a breakpoint and to start the inferior
    125         # which are workarounds for the dwarf case.
    126 
    127         breakpoint = target.BreakpointCreateByLocation('main.c', self.line1)
    128         self.assertTrue(breakpoint, VALID_BREAKPOINT)
    129 
    130         # Now launch the process, and do not stop at entry point.
    131         process = target.LaunchSimple(None, None, os.getcwd())
    132         self.assertTrue(process, PROCESS_IS_VALID)
    133         # Make sure we hit our breakpoint:
    134         thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint)
    135         self.assertTrue (len(thread_list) == 1)
    136 
    137         value_list = target.FindGlobalVariables('my_global_var_of_char_type', 3)
    138         self.assertTrue(value_list.GetSize() == 1)
    139         my_global_var = value_list.GetValueAtIndex(0)
    140         self.DebugSBValue(my_global_var)
    141         self.assertTrue(my_global_var)
    142         self.expect(my_global_var.GetName(), exe=False,
    143             startstr = "my_global_var_of_char_type")
    144         self.expect(my_global_var.GetTypeName(), exe=False,
    145             startstr = "char")
    146         self.expect(my_global_var.GetValue(), exe=False,
    147             startstr = "'X'")
    148 
    149         # While we are at it, let's also exercise the similar SBModule.FindGlobalVariables() API.
    150         for m in target.module_iter():
    151             if m.GetFileSpec().GetDirectory() == os.getcwd() and m.GetFileSpec().GetFilename() == exe_name:
    152                 value_list = m.FindGlobalVariables(target, 'my_global_var_of_char_type', 3)
    153                 self.assertTrue(value_list.GetSize() == 1)
    154                 self.assertTrue(value_list.GetValueAtIndex(0).GetValue() == "'X'")
    155                 break
    156 
    157     def find_functions(self, exe_name):
    158         """Exercise SBTaget.FindFunctions() API."""
    159         exe = os.path.join(os.getcwd(), exe_name)
    160 
    161         # Create a target by the debugger.
    162         target = self.dbg.CreateTarget(exe)
    163         self.assertTrue(target, VALID_TARGET)
    164 
    165         list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto)
    166         self.assertTrue(list.GetSize() == 1)
    167 
    168         for sc in list:
    169             self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() == exe_name)
    170             self.assertTrue(sc.GetSymbol().GetName() == 'c')                
    171 
    172     def get_description(self):
    173         """Exercise SBTaget.GetDescription() API."""
    174         exe = os.path.join(os.getcwd(), "a.out")
    175 
    176         # Create a target by the debugger.
    177         target = self.dbg.CreateTarget(exe)
    178         self.assertTrue(target, VALID_TARGET)
    179 
    180         from lldbutil import get_description
    181 
    182         # get_description() allows no option to mean lldb.eDescriptionLevelBrief.
    183         desc = get_description(target)
    184         #desc = get_description(target, option=lldb.eDescriptionLevelBrief)
    185         if not desc:
    186             self.fail("SBTarget.GetDescription() failed")
    187         self.expect(desc, exe=False,
    188             substrs = ['a.out'])
    189         self.expect(desc, exe=False, matching=False,
    190             substrs = ['Target', 'Module', 'Breakpoint'])
    191 
    192         desc = get_description(target, option=lldb.eDescriptionLevelFull)
    193         if not desc:
    194             self.fail("SBTarget.GetDescription() failed")
    195         self.expect(desc, exe=False,
    196             substrs = ['a.out', 'Target', 'Module', 'Breakpoint'])
    197 
    198 
    199     def launch_new_process_and_redirect_stdout(self):
    200         """Exercise SBTaget.Launch() API with redirected stdout."""
    201         exe = os.path.join(os.getcwd(), "a.out")
    202 
    203         # Create a target by the debugger.
    204         target = self.dbg.CreateTarget(exe)
    205         self.assertTrue(target, VALID_TARGET)
    206 
    207         # Add an extra twist of stopping the inferior in a breakpoint, and then continue till it's done.
    208         # We should still see the entire stdout redirected once the process is finished.
    209         line = line_number('main.c', '// a(3) -> c(3)')
    210         breakpoint = target.BreakpointCreateByLocation('main.c', line)
    211 
    212         # Now launch the process, do not stop at entry point, and redirect stdout to "stdout.txt" file.
    213         # The inferior should run to completion after "process.Continue()" call.
    214         error = lldb.SBError()
    215         process = target.Launch (self.dbg.GetListener(), None, None, None, "stdout.txt", None, None, 0, False, error)
    216         process.Continue()
    217         #self.runCmd("process status")
    218 
    219         # The 'stdout.txt' file should now exist.
    220         self.assertTrue(os.path.isfile("stdout.txt"),
    221                         "'stdout.txt' exists due to redirected stdout via SBTarget.Launch() API.")
    222 
    223         # Read the output file produced by running the program.
    224         with open('stdout.txt', 'r') as f:
    225             output = f.read()
    226 
    227         # Let's delete the 'stdout.txt' file as a cleanup step.
    228         try:
    229             os.remove("stdout.txt")
    230             pass
    231         except OSError:
    232             pass
    233 
    234         self.expect(output, exe=False,
    235             substrs = ["a(1)", "b(2)", "a(3)"])
    236 
    237 
    238     def resolve_symbol_context_with_address(self):
    239         """Exercise SBTaget.ResolveSymbolContextForAddress() API."""
    240         exe = os.path.join(os.getcwd(), "a.out")
    241 
    242         # Create a target by the debugger.
    243         target = self.dbg.CreateTarget(exe)
    244         self.assertTrue(target, VALID_TARGET)
    245 
    246         # Now create the two breakpoints inside function 'a'.
    247         breakpoint1 = target.BreakpointCreateByLocation('main.c', self.line1)
    248         breakpoint2 = target.BreakpointCreateByLocation('main.c', self.line2)
    249         #print "breakpoint1:", breakpoint1
    250         #print "breakpoint2:", breakpoint2
    251         self.assertTrue(breakpoint1 and
    252                         breakpoint1.GetNumLocations() == 1,
    253                         VALID_BREAKPOINT)
    254         self.assertTrue(breakpoint2 and
    255                         breakpoint2.GetNumLocations() == 1,
    256                         VALID_BREAKPOINT)
    257 
    258         # Now launch the process, and do not stop at entry point.
    259         process = target.LaunchSimple(None, None, os.getcwd())
    260         self.assertTrue(process, PROCESS_IS_VALID)
    261 
    262         # Frame #0 should be on self.line1.
    263         self.assertTrue(process.GetState() == lldb.eStateStopped)
    264         thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
    265         self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition")
    266         #self.runCmd("process status")
    267         frame0 = thread.GetFrameAtIndex(0)
    268         lineEntry = frame0.GetLineEntry()
    269         self.assertTrue(lineEntry.GetLine() == self.line1)
    270 
    271         address1 = lineEntry.GetStartAddress()
    272 
    273         # Continue the inferior, the breakpoint 2 should be hit.
    274         process.Continue()
    275         self.assertTrue(process.GetState() == lldb.eStateStopped)
    276         thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
    277         self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition")
    278         #self.runCmd("process status")
    279         frame0 = thread.GetFrameAtIndex(0)
    280         lineEntry = frame0.GetLineEntry()
    281         self.assertTrue(lineEntry.GetLine() == self.line2)
    282 
    283         address2 = lineEntry.GetStartAddress()
    284 
    285         #print "address1:", address1
    286         #print "address2:", address2
    287 
    288         # Now call SBTarget.ResolveSymbolContextForAddress() with the addresses from our line entry.
    289         context1 = target.ResolveSymbolContextForAddress(address1, lldb.eSymbolContextEverything)
    290         context2 = target.ResolveSymbolContextForAddress(address2, lldb.eSymbolContextEverything)
    291 
    292         self.assertTrue(context1 and context2)
    293         #print "context1:", context1
    294         #print "context2:", context2
    295 
    296         # Verify that the context point to the same function 'a'.
    297         symbol1 = context1.GetSymbol()
    298         symbol2 = context2.GetSymbol()
    299         self.assertTrue(symbol1 and symbol2)
    300         #print "symbol1:", symbol1
    301         #print "symbol2:", symbol2
    302 
    303         from lldbutil import get_description
    304         desc1 = get_description(symbol1)
    305         desc2 = get_description(symbol2)
    306         self.assertTrue(desc1 and desc2 and desc1 == desc2,
    307                         "The two addresses should resolve to the same symbol")
    308 
    309         
    310 if __name__ == '__main__':
    311     import atexit
    312     lldb.SBDebugger.Initialize()
    313     atexit.register(lambda: lldb.SBDebugger.Terminate())
    314     unittest2.main()
    315