Home | History | Annotate | Download | only in return-value
      1 """
      2 Test getting return-values correctly when stepping out
      3 """
      4 
      5 import os, time
      6 import re
      7 import unittest2
      8 import lldb, lldbutil
      9 from lldbtest import *
     10 
     11 class ReturnValueTestCase(TestBase):
     12 
     13     mydir = os.path.join("functionalities", "return-value")
     14 
     15     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     16     @expectedFailurei386
     17     @python_api_test
     18     @dsym_test
     19     def test_with_dsym_python(self):
     20         """Test getting return values from stepping out with dsyms."""
     21         self.buildDsym()
     22         self.do_return_value()
     23 
     24     @expectedFailurei386
     25     @python_api_test
     26     @dwarf_test
     27     def test_with_dwarf_python(self):
     28         """Test getting return values from stepping out."""
     29         self.buildDwarf()
     30         self.do_return_value()
     31 
     32     def return_and_test_struct_value (self, func_name):
     33         """Pass in the name of the function to return from - takes in value, returns value."""
     34         
     35         # Set the breakpoint, run to it, finish out.
     36         bkpt = self.target.BreakpointCreateByName (func_name)
     37         self.assertTrue (bkpt.GetNumResolvedLocations() > 0)
     38 
     39         self.process.Continue ()
     40 
     41         thread_list = lldbutil.get_threads_stopped_at_breakpoint (self.process, bkpt)
     42 
     43         self.assertTrue (len(thread_list) == 1)
     44         thread = thread_list[0]
     45 
     46         self.target.BreakpointDelete (bkpt.GetID())
     47 
     48         in_value = thread.GetFrameAtIndex(0).FindVariable ("value")
     49         
     50         self.assertTrue (in_value.IsValid())
     51         num_in_children = in_value.GetNumChildren()
     52 
     53         # This is a little hokey, but if we don't get all the children now, then
     54         # once we've stepped we won't be able to get them?
     55         
     56         for idx in range(0, num_in_children):
     57             in_child = in_value.GetChildAtIndex (idx)
     58             in_child_str = in_child.GetValue()
     59 
     60         thread.StepOut()
     61         
     62         self.assertTrue (self.process.GetState() == lldb.eStateStopped)
     63         self.assertTrue (thread.GetStopReason() == lldb.eStopReasonPlanComplete)
     64 
     65         # Assuming all these functions step out to main.  Could figure out the caller dynamically
     66         # if that would add something to the test.
     67         frame = thread.GetFrameAtIndex(0)
     68         fun_name = frame.GetFunctionName()
     69         self.assertTrue (fun_name == "main")
     70 
     71         frame = thread.GetFrameAtIndex(0)
     72         ret_value = thread.GetStopReturnValue()
     73 
     74         self.assertTrue (ret_value.IsValid())
     75 
     76         num_ret_children = ret_value.GetNumChildren()
     77         self.assertTrue (num_in_children == num_ret_children)
     78         for idx in range(0, num_ret_children):
     79             in_child = in_value.GetChildAtIndex(idx)
     80             ret_child = ret_value.GetChildAtIndex(idx)
     81             in_child_str = in_child.GetValue()
     82             ret_child_str = ret_child.GetValue()
     83 
     84             self.assertTrue (in_child_str == ret_child_str)
     85 
     86     def do_return_value(self):
     87         """Test getting return values from stepping out."""
     88         exe = os.path.join(os.getcwd(), "a.out")
     89         error = lldb.SBError()
     90 
     91         self.target = self.dbg.CreateTarget(exe)
     92         self.assertTrue(self.target, VALID_TARGET)
     93 
     94         inner_sint_bkpt = self.target.BreakpointCreateByName("inner_sint", exe)
     95         self.assertTrue(inner_sint_bkpt, VALID_BREAKPOINT)
     96 
     97         # Now launch the process, and do not stop at entry point.
     98         self.process = self.target.LaunchSimple(None, None, os.getcwd())
     99 
    100         self.assertTrue(self.process, PROCESS_IS_VALID)
    101 
    102         # The stop reason of the thread should be breakpoint.
    103         self.assertTrue(self.process.GetState() == lldb.eStateStopped,
    104                         STOPPED_DUE_TO_BREAKPOINT)
    105 
    106         # Now finish, and make sure the return value is correct.
    107         thread = lldbutil.get_stopped_thread (self.process, lldb.eStopReasonBreakpoint)
    108 
    109         # inner_sint returns the variable value, so capture that here:
    110         in_int = thread.GetFrameAtIndex(0).FindVariable ("value").GetValueAsSigned(error)
    111         self.assertTrue (error.Success())
    112 
    113         thread.StepOut();
    114 
    115         self.assertTrue (self.process.GetState() == lldb.eStateStopped)
    116         self.assertTrue (thread.GetStopReason() == lldb.eStopReasonPlanComplete)
    117 
    118         frame = thread.GetFrameAtIndex(0)
    119         fun_name = frame.GetFunctionName()
    120         self.assertTrue (fun_name == "outer_sint")
    121 
    122         return_value = thread.GetStopReturnValue()
    123         self.assertTrue (return_value.IsValid())
    124 
    125         ret_int = return_value.GetValueAsSigned(error)
    126         self.assertTrue (error.Success())
    127         self.assertTrue (in_int == ret_int)
    128 
    129         # Run again and we will stop in inner_sint the second time outer_sint is called.  
    130         #Then test stepping out two frames at once:
    131 
    132         self.process.Continue()
    133         thread_list = lldbutil.get_threads_stopped_at_breakpoint (self.process, inner_sint_bkpt)
    134         self.assertTrue(len(thread_list) == 1)
    135         thread = thread_list[0]
    136 
    137         # We are done with the inner_sint breakpoint:
    138         self.target.BreakpointDelete (inner_sint_bkpt.GetID())
    139 
    140         frame = thread.GetFrameAtIndex(1)
    141         fun_name = frame.GetFunctionName ()
    142         self.assertTrue (fun_name == "outer_sint")
    143         in_int = frame.FindVariable ("value").GetValueAsSigned(error)
    144         self.assertTrue (error.Success())
    145 
    146         thread.StepOutOfFrame (frame)
    147 
    148         self.assertTrue (self.process.GetState() == lldb.eStateStopped)
    149         self.assertTrue (thread.GetStopReason() == lldb.eStopReasonPlanComplete)
    150         frame = thread.GetFrameAtIndex(0)
    151         fun_name = frame.GetFunctionName()
    152         self.assertTrue (fun_name == "main")
    153 
    154         ret_value = thread.GetStopReturnValue()
    155         self.assertTrue (return_value.IsValid())
    156         ret_int = ret_value.GetValueAsSigned (error)
    157         self.assertTrue (error.Success())
    158         self.assertTrue (2 * in_int == ret_int)
    159         
    160         # Now try some simple returns that have different types:
    161         inner_float_bkpt = self.target.BreakpointCreateByName("inner_float", exe)
    162         self.assertTrue(inner_float_bkpt, VALID_BREAKPOINT)
    163         self.process.Continue()
    164         thread_list = lldbutil.get_threads_stopped_at_breakpoint (self.process, inner_float_bkpt)
    165         self.assertTrue (len(thread_list) == 1)
    166         thread = thread_list[0]
    167 
    168         self.target.BreakpointDelete (inner_float_bkpt.GetID())
    169 
    170         frame = thread.GetFrameAtIndex(0)
    171         in_value = frame.FindVariable ("value")
    172         in_float = float (in_value.GetValue())
    173         thread.StepOut()
    174 
    175         self.assertTrue (self.process.GetState() == lldb.eStateStopped)
    176         self.assertTrue (thread.GetStopReason() == lldb.eStopReasonPlanComplete)
    177 
    178         frame = thread.GetFrameAtIndex(0)
    179         fun_name = frame.GetFunctionName()
    180         self.assertTrue (fun_name == "outer_float")
    181 
    182         return_value = thread.GetStopReturnValue()
    183         self.assertTrue (return_value.IsValid())
    184         return_float = float (return_value.GetValue())
    185 
    186         self.assertTrue(in_float == return_float)
    187 
    188         self.return_and_test_struct_value ("return_one_int")
    189         self.return_and_test_struct_value ("return_two_int")
    190         self.return_and_test_struct_value ("return_three_int")
    191         self.return_and_test_struct_value ("return_four_int")
    192         self.return_and_test_struct_value ("return_five_int")
    193         
    194         self.return_and_test_struct_value ("return_two_double")
    195         self.return_and_test_struct_value ("return_one_double_two_float")
    196         self.return_and_test_struct_value ("return_one_int_one_float_one_int")
    197         
    198         self.return_and_test_struct_value ("return_one_pointer")
    199         self.return_and_test_struct_value ("return_two_pointer")
    200         self.return_and_test_struct_value ("return_one_float_one_pointer")
    201         self.return_and_test_struct_value ("return_one_int_one_pointer")
    202         self.return_and_test_struct_value ("return_three_short_one_float")
    203 
    204         self.return_and_test_struct_value ("return_one_int_one_double")
    205         self.return_and_test_struct_value ("return_one_int_one_double_one_int")
    206         self.return_and_test_struct_value ("return_one_short_one_double_one_short")
    207         self.return_and_test_struct_value ("return_one_float_one_int_one_float")
    208         self.return_and_test_struct_value ("return_two_float")
    209         # I am leaving out the packed test until we have a way to tell CLANG 
    210         # about alignment when reading DWARF for packed types.
    211         #self.return_and_test_struct_value ("return_one_int_one_double_packed")
    212         self.return_and_test_struct_value ("return_one_int_one_long")
    213 
    214         # icc and gcc don't support this extension.
    215         if self.getCompiler().endswith('clang'):
    216             self.return_and_test_struct_value ("return_vector_size_float32")
    217             self.return_and_test_struct_value ("return_ext_vector_size_float32")
    218 
    219         
    220 if __name__ == '__main__':
    221     import atexit
    222     lldb.SBDebugger.Initialize()
    223     atexit.register(lambda: lldb.SBDebugger.Terminate())
    224     unittest2.main()
    225