diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2016-01-06 20:12:03 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2016-01-06 20:12:03 +0000 | 
| commit | 9e6d35490a6542f9c97607f93c2ef8ca8e03cbcc (patch) | |
| tree | dd2a1ddf0476664c2b823409c36cbccd52662ca7 /packages/Python/lldbsuite/test/lang/objc | |
| parent | 3bd2e91faeb9eeec1aae82c64a3253afff551cfd (diff) | |
Notes
Diffstat (limited to 'packages/Python/lldbsuite/test/lang/objc')
140 files changed, 5386 insertions, 0 deletions
| diff --git a/packages/Python/lldbsuite/test/lang/objc/.categories b/packages/Python/lldbsuite/test/lang/objc/.categories new file mode 100644 index 000000000000..72cf07c1efea --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/.categories @@ -0,0 +1 @@ +objc diff --git a/packages/Python/lldbsuite/test/lang/objc/blocks/Makefile b/packages/Python/lldbsuite/test/lang/objc/blocks/Makefile new file mode 100644 index 000000000000..0af83591826f --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/blocks/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := ivars-in-blocks.m main.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/blocks/TestObjCIvarsInBlocks.py b/packages/Python/lldbsuite/test/lang/objc/blocks/TestObjCIvarsInBlocks.py new file mode 100644 index 000000000000..6a1cde1a3cb3 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/blocks/TestObjCIvarsInBlocks.py @@ -0,0 +1,103 @@ +"""Test printing ivars and ObjC objects captured in blocks that are made in methods of an ObjC class.""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class TestObjCIvarsInBlocks(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line numbers to break inside main(). +        self.main_source = "main.m" +        self.class_source = "ivars-in-blocks.m" +        self.class_source_file_spec = lldb.SBFileSpec(self.class_source) + +    @skipUnlessDarwin +    @add_test_categories(['pyapi']) +    @expectedFailurei386 # This test requires the 2.0 runtime, so it will fail on i386. +    def test_with_python_api(self): +        """Test printing the ivars of the self when captured in blocks""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        breakpoint = target.BreakpointCreateBySourceRegex ('// Break here inside the block.', self.class_source_file_spec) +        self.assertTrue(breakpoint, VALID_BREAKPOINT) + +        breakpoint_two = target.BreakpointCreateBySourceRegex ('// Break here inside the class method block.', self.class_source_file_spec) +        self.assertTrue(breakpoint, VALID_BREAKPOINT) + +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) +        self.assertTrue (process, "Created a process.") +        self.assertTrue (process.GetState() == lldb.eStateStopped, "Stopped it too.") + +        thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint) +        self.assertTrue (len(thread_list) == 1) +        thread = thread_list[0] +         +        frame = thread.GetFrameAtIndex(0) +        self.assertTrue (frame, "frame 0 is valid") +         +        # First use the FindVariable API to see if we can find the ivar by undecorated name: +        direct_blocky = frame.GetValueForVariablePath ("blocky_ivar") +        self.assertTrue(direct_blocky, "Found direct access to blocky_ivar.") +         +        # Now get it as a member of "self" and make sure the two values are equal: +        self_var = frame.GetValueForVariablePath ("self") +        self.assertTrue (self_var, "Found self in block.") +        indirect_blocky = self_var.GetChildMemberWithName ("blocky_ivar") +        self.assertTrue (indirect_blocky, "Found blocky_ivar through self") +         +        error = lldb.SBError() +        direct_value = direct_blocky.GetValueAsSigned(error) +        self.assertTrue (error.Success(), "Got direct value for blocky_ivar") + +        indirect_value = indirect_blocky.GetValueAsSigned (error) +        self.assertTrue (error.Success(), "Got indirect value for blocky_ivar") +         +        self.assertTrue (direct_value == indirect_value, "Direct and indirect values are equal.") + +        # Now make sure that we can get at the captured ivar through the expression parser. +        # Doing a little trivial math will force this into the real expression parser: +        direct_expr = frame.EvaluateExpression ("blocky_ivar + 10") +        self.assertTrue (direct_expr, "Got blocky_ivar through the expression parser") +         +        # Again, get the value through self directly and make sure they are the same: +        indirect_expr = frame.EvaluateExpression ("self->blocky_ivar + 10") +        self.assertTrue (indirect_expr, "Got blocky ivar through expression parser using self.") +         +        direct_value = direct_expr.GetValueAsSigned (error) +        self.assertTrue (error.Success(), "Got value from direct use of expression parser") + +        indirect_value = indirect_expr.GetValueAsSigned (error) +        self.assertTrue (error.Success(), "Got value from indirect access using the expression parser") + +        self.assertTrue (direct_value == indirect_value, "Direct ivar access and indirect through expression parser produce same value.") + +        process.Continue() +        self.assertTrue (process.GetState() == lldb.eStateStopped, "Stopped at the second breakpoint.") + +        thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint_two) +        self.assertTrue (len(thread_list) == 1) +        thread = thread_list[0] +         +        frame = thread.GetFrameAtIndex(0) +        self.assertTrue (frame, "frame 0 is valid") +         +        expr = frame.EvaluateExpression("(ret)") +        self.assertTrue (expr, "Successfully got a local variable in a block in a class method.") + +        ret_value_signed = expr.GetValueAsSigned (error) +        # print('ret_value_signed = %i' % (ret_value_signed)) +        self.assertTrue (ret_value_signed == 5, "The local variable in the block was what we expected.") diff --git a/packages/Python/lldbsuite/test/lang/objc/blocks/ivars-in-blocks.h b/packages/Python/lldbsuite/test/lang/objc/blocks/ivars-in-blocks.h new file mode 100644 index 000000000000..1ceac3361ac0 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/blocks/ivars-in-blocks.h @@ -0,0 +1,11 @@ +#import <Foundation/Foundation.h> + +@interface IAmBlocky : NSObject +{ +  @public +  int blocky_ivar; +} ++ (void) classMethod; +- (IAmBlocky *) init; +- (int) callABlock: (int) block_value; +@end diff --git a/packages/Python/lldbsuite/test/lang/objc/blocks/ivars-in-blocks.m b/packages/Python/lldbsuite/test/lang/objc/blocks/ivars-in-blocks.m new file mode 100644 index 000000000000..1098a9136ae2 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/blocks/ivars-in-blocks.m @@ -0,0 +1,57 @@ +#import "ivars-in-blocks.h" + +typedef int (^my_block_ptr_type) (int); + +@interface IAmBlocky() +{ +  int _hidden_ivar; +  my_block_ptr_type _block_ptr; +} + +@end + +@implementation IAmBlocky + ++ (int) addend +{ +  return 3; +} +  ++ (void) classMethod +{ +  int (^my_block)(int) = ^(int foo) +  { +    int ret = foo + [self addend]; +    return ret; // Break here inside the class method block. +  }; +  printf("%d\n", my_block(2)); +} + +- (void) makeBlockPtr; +{ +  _block_ptr = ^(int inval) +  { +    _hidden_ivar += inval; +    return blocky_ivar * inval; // Break here inside the block. +  }; +} + +- (IAmBlocky *) init +{ +  blocky_ivar = 10; +  _hidden_ivar = 20; +  // Interesting...  Apparently you can't make a block in your init method.  This crashes... +  // [self makeBlockPtr]; +  return self; +} + +- (int) callABlock: (int) block_value +{ +  if (_block_ptr == NULL) +    [self makeBlockPtr]; +  int ret = _block_ptr (block_value); +  [IAmBlocky classMethod]; +  return ret; +} +@end + diff --git a/packages/Python/lldbsuite/test/lang/objc/blocks/main.m b/packages/Python/lldbsuite/test/lang/objc/blocks/main.m new file mode 100644 index 000000000000..0c56f45da464 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/blocks/main.m @@ -0,0 +1,10 @@ +#import "ivars-in-blocks.h" + +int +main (int argc, char **argv) +{ +  IAmBlocky *my_blocky = [[IAmBlocky alloc] init]; +  int blocky_value; +  blocky_value = [my_blocky callABlock: 33]; +  return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/objc/forward-decl/Container.h b/packages/Python/lldbsuite/test/lang/objc/forward-decl/Container.h new file mode 100644 index 000000000000..85bbd06b161c --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/forward-decl/Container.h @@ -0,0 +1,13 @@ +#import <Foundation/Foundation.h> + +@class ForwardDeclaredClass; + +@interface Container : NSObject { +@public +    ForwardDeclaredClass *member; +} + +-(id)init; +-(ForwardDeclaredClass*)getMember; + +@end diff --git a/packages/Python/lldbsuite/test/lang/objc/forward-decl/Container.m b/packages/Python/lldbsuite/test/lang/objc/forward-decl/Container.m new file mode 100644 index 000000000000..4d2139ff5fc6 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/forward-decl/Container.m @@ -0,0 +1,27 @@ +#import "Container.h" + +@interface ForwardDeclaredClass : NSObject +{ +    int a; +    int b; +} +@end + +@implementation ForwardDeclaredClass + +@end + +@implementation Container + +-(id)init +{ +    member = [ForwardDeclaredClass alloc]; +    return [super init]; +} + +-(ForwardDeclaredClass *)getMember +{ +    return member; +} + +@end diff --git a/packages/Python/lldbsuite/test/lang/objc/forward-decl/Makefile b/packages/Python/lldbsuite/test/lang/objc/forward-decl/Makefile new file mode 100644 index 000000000000..b99925b50b38 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/forward-decl/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +DYLIB_NAME := Container +DYLIB_OBJC_SOURCES := Container.m +OBJC_SOURCES := main.m + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation diff --git a/packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py b/packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py new file mode 100644 index 000000000000..207518abc91b --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py @@ -0,0 +1,54 @@ +"""Test that a forward-declared class works when its complete definition is in a library""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class ForwardDeclTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break inside main(). +        self.source = 'main.m' +        self.line = line_number(self.source, '// Set breakpoint 0 here.') +        self.shlib_names = ["Container"] + +    @skipUnlessDarwin +    def test_expr(self): +        self.build() +         +        # Create a target by the debugger. +        target = self.dbg.CreateTarget("a.out") +        self.assertTrue(target, VALID_TARGET) + +        # Create the breakpoint inside function 'main'. +        breakpoint = target.BreakpointCreateByLocation(self.source, self.line) +        self.assertTrue(breakpoint, VALID_BREAKPOINT) +         +        # Register our shared libraries for remote targets so they get automatically uploaded +        environment = self.registerSharedLibrariesWithTarget(target, self.shlib_names) + +        # Now launch the process, and do not stop at entry point. +        process = target.LaunchSimple (None, environment, self.get_process_working_directory()) +        self.assertTrue(process, PROCESS_IS_VALID) + +        # The stop reason of the thread should be breakpoint. +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +            substrs = ['stopped', +                       'stop reason = breakpoint']) + +        # The breakpoint should have a hit count of 1. +        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, +            substrs = [' resolved, hit count = 1']) + +        # This should display correctly. +        self.expect("expression [j getMember]", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["= 0x"]) diff --git a/packages/Python/lldbsuite/test/lang/objc/forward-decl/main.m b/packages/Python/lldbsuite/test/lang/objc/forward-decl/main.m new file mode 100644 index 000000000000..8e5256e95230 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/forward-decl/main.m @@ -0,0 +1,14 @@ +#import <Foundation/Foundation.h> +#import "Container.h" + +int main(int argc, const char * argv[]) +{ + +    @autoreleasepool { +        Container *j = [[Container alloc] init]; + +        printf("member value = %p", [j getMember]); // Set breakpoint 0 here. +    }    +    return 0; +} + diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/Makefile b/packages/Python/lldbsuite/test/lang/objc/foundation/Makefile new file mode 100644 index 000000000000..ce2ccd28321d --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m my-base.m +#OBJC_SOURCES := const-strings.m + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/TestConstStrings.py b/packages/Python/lldbsuite/test/lang/objc/foundation/TestConstStrings.py new file mode 100644 index 000000000000..a9298dd81cf8 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/TestConstStrings.py @@ -0,0 +1,53 @@ +""" +Test that objective-c constant strings are generated correctly by the expression +parser. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class ConstStringTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) +    d = {'OBJC_SOURCES': 'const-strings.m'} + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break inside main(). +        self.main_source = "const-strings.m" +        self.line = line_number(self.main_source, '// Set breakpoint here.') + +    @skipUnlessDarwin +    def test_break(self): +        """Test constant string generation amd comparison by the expression parser.""" +        self.build(dictionary=self.d) +        self.setTearDownCleanup(self.d) +         +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        lldbutil.run_break_set_by_file_and_line (self, self.main_source, self.line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) +        self.expect("process status", STOPPED_DUE_TO_BREAKPOINT, +            substrs = [" at %s:%d" % (self.main_source, self.line), +                       "stop reason = breakpoint"]) + +        self.expect('expression (int)[str compare:@"hello"]', +            startstr = "(int) $0 = 0") +        self.expect('expression (int)[str compare:@"world"]', +            startstr = "(int) $1 = -1") + +        # Test empty strings, too. +        self.expect('expression (int)[@"" length]', +            startstr = "(int) $2 = 0") + +        self.expect('expression (int)[@"123" length]', +            startstr = "(int) $3 = 3") diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/TestFoundationDisassembly.py b/packages/Python/lldbsuite/test/lang/objc/foundation/TestFoundationDisassembly.py new file mode 100644 index 000000000000..88db12e95931 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/TestFoundationDisassembly.py @@ -0,0 +1,134 @@ +""" +Test the lldb disassemble command on foundation framework. +""" + +from __future__ import print_function + + + +import unittest2 +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +@skipUnlessDarwin +class FoundationDisassembleTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    # rdar://problem/8504895 +    # Crash while doing 'disassemble -n "-[NSNumber descriptionWithLocale:]" +    @unittest2.skipIf(TestBase.skipLongRunningTest(), "Skip this long running test") +    def test_foundation_disasm(self): +        """Do 'disassemble -n func' on each and every 'Code' symbol entry from the Foundation.framework.""" +        self.build() +         +        # Enable synchronous mode +        self.dbg.SetAsync(False) +         +        # Create a target by the debugger. +        target = self.dbg.CreateTarget("a.out") +        self.assertTrue(target, VALID_TARGET) + +        # Now launch the process, and do not stop at entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) +        self.assertTrue(process, PROCESS_IS_VALID) + +        foundation_framework = None +        for module in target.modules: +            print(module) +            if module.file.basename == "Foundation": +                foundation_framework = module.file.fullpath +                break + +        self.assertTrue(foundation_framework != None, "Foundation.framework path located") +        self.runCmd("image dump symtab '%s'" % foundation_framework) +        raw_output = self.res.GetOutput() +        # Now, grab every 'Code' symbol and feed it into the command: +        # 'disassemble -n func'. +        # +        # The symbol name is on the last column and trails the flag column which +        # looks like '0xhhhhhhhh', i.e., 8 hexadecimal digits. +        codeRE = re.compile(r""" +                             \ Code\ {9}    # ' Code' followed by 9 SPCs, +                             .*             # the wildcard chars, +                             0x[0-9a-f]{8}  # the flag column, and +                             \ (.+)$        # finally the function symbol. +                             """, re.VERBOSE) +        for line in raw_output.split(os.linesep): +            match = codeRE.search(line) +            if match: +                func = match.group(1) +                #print("line:", line) +                #print("func:", func) +                self.runCmd('disassemble -n "%s"' % func) +         + +    def test_simple_disasm(self): +        """Test the lldb 'disassemble' command""" +        self.build() + +        # Create a target by the debugger. +        target = self.dbg.CreateTarget("a.out") +        self.assertTrue(target, VALID_TARGET) + +        print(target) +        for module in target.modules: +            print(module) + +        # Stop at +[NSString stringWithFormat:]. +        symbol_name = "+[NSString stringWithFormat:]" +        break_results = lldbutil.run_break_set_command (self, "_regexp-break %s"%(symbol_name)) +         +        lldbutil.check_breakpoint_result (self, break_results, symbol_name=symbol_name, num_locations=1) + +        # Stop at -[MyString initWithNSString:]. +        lldbutil.run_break_set_by_symbol (self, '-[MyString initWithNSString:]', num_expected_locations=1, sym_exact=True) + +        # Stop at the "description" selector. +        lldbutil.run_break_set_by_selector (self, 'description', num_expected_locations=1, module_name='a.out') + +        # Stop at -[NSAutoreleasePool release]. +        break_results = lldbutil.run_break_set_command (self, "_regexp-break -[NSAutoreleasePool release]") +        lldbutil.check_breakpoint_result (self, break_results, symbol_name='-[NSAutoreleasePool release]', num_locations=1) + +        self.runCmd("run", RUN_SUCCEEDED) + +        # First stop is +[NSString stringWithFormat:]. +        self.expect("thread backtrace", "Stop at +[NSString stringWithFormat:]", +            substrs = ["Foundation`+[NSString stringWithFormat:]"]) + +        # Do the disassemble for the currently stopped function. +        self.runCmd("disassemble -f") + +        self.runCmd("process continue") +        # Skip another breakpoint for +[NSString stringWithFormat:]. +        self.runCmd("process continue") + +        # Followed by a.out`-[MyString initWithNSString:]. +        self.expect("thread backtrace", "Stop at a.out`-[MyString initWithNSString:]", +            substrs = ["a.out`-[MyString initWithNSString:]"]) + +        # Do the disassemble for the currently stopped function. +        self.runCmd("disassemble -f") + +        self.runCmd("process continue") + +        # Followed by -[MyString description]. +        self.expect("thread backtrace", "Stop at -[MyString description]", +            substrs = ["a.out`-[MyString description]"]) + +        # Do the disassemble for the currently stopped function. +        self.runCmd("disassemble -f") + +        self.runCmd("process continue") +        # Skip another breakpoint for -[MyString description]. +        self.runCmd("process continue") + +        # Followed by -[NSAutoreleasePool release]. +        self.expect("thread backtrace", "Stop at -[NSAutoreleasePool release]", +            substrs = ["Foundation`-[NSAutoreleasePool release]"]) + +        # Do the disassemble for the currently stopped function. +        self.runCmd("disassemble -f") diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods.py b/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods.py new file mode 100644 index 000000000000..8358bd5e923f --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods.py @@ -0,0 +1,262 @@ +""" +Set breakpoints on objective-c class and instance methods in foundation. +Also lookup objective-c data types and evaluate expressions. +""" + +from __future__ import print_function + + + +import os, os.path, time +import lldb +import string +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +file_index = 0 +@skipUnlessDarwin +class FoundationTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break inside main(). +        self.main_source = "main.m" +        self.line = line_number(self.main_source, '// Set break point at this line.') + +    def test_break(self): +        """Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # Stop at +[NSString stringWithFormat:]. +        break_results = lldbutil.run_break_set_command(self, "_regexp-break +[NSString stringWithFormat:]") +        lldbutil.check_breakpoint_result (self, break_results, symbol_name='+[NSString stringWithFormat:]', num_locations=1) + +        # Stop at -[MyString initWithNSString:]. +        lldbutil.run_break_set_by_symbol (self, '-[MyString initWithNSString:]', num_expected_locations=1, sym_exact=True) + +        # Stop at the "description" selector. +        lldbutil.run_break_set_by_selector (self, 'description', num_expected_locations=1, module_name='a.out') + +        # Stop at -[NSAutoreleasePool release]. +        break_results = lldbutil.run_break_set_command(self, "_regexp-break -[NSAutoreleasePool release]") +        lldbutil.check_breakpoint_result (self, break_results, symbol_name='-[NSAutoreleasePool release]', num_locations=1) + +        self.runCmd("run", RUN_SUCCEEDED) + +        # First stop is +[NSString stringWithFormat:]. +        self.expect("thread backtrace", "Stop at +[NSString stringWithFormat:]", +            substrs = ["Foundation`+[NSString stringWithFormat:]"]) + +        self.runCmd("process continue") + +        # Second stop is still +[NSString stringWithFormat:]. +        self.expect("thread backtrace", "Stop at +[NSString stringWithFormat:]", +            substrs = ["Foundation`+[NSString stringWithFormat:]"]) + +        self.runCmd("process continue") + +        # Followed by a.out`-[MyString initWithNSString:]. +        self.expect("thread backtrace", "Stop at a.out`-[MyString initWithNSString:]", +            substrs = ["a.out`-[MyString initWithNSString:]"]) + +        self.runCmd("process continue") + +        # Followed by -[MyString description]. +        self.expect("thread backtrace", "Stop at -[MyString description]", +            substrs = ["a.out`-[MyString description]"]) + +        self.runCmd("process continue") + +        # Followed by the same -[MyString description]. +        self.expect("thread backtrace", "Stop at -[MyString description]", +            substrs = ["a.out`-[MyString description]"]) + +        self.runCmd("process continue") + +        # Followed by -[NSAutoreleasePool release]. +        self.expect("thread backtrace", "Stop at -[NSAutoreleasePool release]", +            substrs = ["Foundation`-[NSAutoreleasePool release]"]) + +    # rdar://problem/8542091 +    # rdar://problem/8492646 +    def test_data_type_and_expr(self): +        """Lookup objective-c data types and evaluate expressions.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # Stop at -[MyString description]. +        lldbutil.run_break_set_by_symbol (self, '-[MyString description]', num_expected_locations=1, sym_exact=True) +#        self.expect("breakpoint set -n '-[MyString description]", BREAKPOINT_CREATED, +#            startstr = "Breakpoint created: 1: name = '-[MyString description]', locations = 1") + +        self.runCmd("run", RUN_SUCCEEDED) + +        # The backtrace should show we stop at -[MyString description]. +        self.expect("thread backtrace", "Stop at -[MyString description]", +            substrs = ["a.out`-[MyString description]"]) + +        # Lookup objc data type MyString and evaluate some expressions. + +        self.expect("image lookup -t NSString", DATA_TYPES_DISPLAYED_CORRECTLY, +            substrs = ['name = "NSString"', +                       'compiler_type = "@interface NSString']) + +        self.expect("image lookup -t MyString", DATA_TYPES_DISPLAYED_CORRECTLY, +            substrs = ['name = "MyString"', +                       'compiler_type = "@interface MyString', +                       'NSString * str;', +                       'NSDate * date;']) + +        self.expect("frame variable --show-types --scope", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["ARG: (MyString *) self"], +            patterns = ["ARG: \(.*\) _cmd", +                        "(objc_selector *)|(SEL)"]) + +        # rdar://problem/8651752 +        # don't crash trying to ask clang how many children an empty record has +        self.runCmd("frame variable *_cmd") + +        # rdar://problem/8492646 +        # test/foundation fails after updating to tot r115023 +        # self->str displays nothing as output +        self.expect("frame variable --show-types self->str", VARIABLES_DISPLAYED_CORRECTLY, +            startstr = "(NSString *) self->str") + +        # rdar://problem/8447030 +        # 'frame variable self->date' displays the wrong data member +        self.expect("frame variable --show-types self->date", VARIABLES_DISPLAYED_CORRECTLY, +            startstr = "(NSDate *) self->date") + +        # This should display the str and date member fields as well. +        self.expect("frame variable --show-types *self", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["(MyString) *self", +                       "(NSString *) str", +                       "(NSDate *) date"]) +         +        # isa should be accessible. +        self.expect("expression self->isa", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["(Class)"]) + +        # This should fail expectedly. +        self.expect("expression self->non_existent_member", +                    COMMAND_FAILED_AS_EXPECTED, error=True, +            startstr = "error: 'MyString' does not have a member named 'non_existent_member'") + +        # Use expression parser. +        self.runCmd("expression self->str") +        self.runCmd("expression self->date") + +        # (lldb) expression self->str +        # error: instance variable 'str' is protected +        # error: 1 errors parsing expression +        # +        # (lldb) expression self->date +        # error: instance variable 'date' is protected +        # error: 1 errors parsing expression +        # + +        self.runCmd("breakpoint delete 1") +        lldbutil.run_break_set_by_file_and_line (self, "main.m", self.line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("process continue") + +        # rdar://problem/8542091 +        # test/foundation: expr -o -- my not working? +        # +        # Test new feature with r115115: +        # Add "-o" option to "expression" which prints the object description if available. +        self.expect("expression --object-description -- my", "Object description displayed correctly", +            patterns = ["Hello from.*a.out.*with timestamp: "]) + +    @add_test_categories(['pyapi']) +    def test_print_ivars_correctly (self): +        self.build() +        # See: <rdar://problem/8717050> lldb needs to use the ObjC runtime symbols for ivar offsets +        # Only fails for the ObjC 2.0 runtime. +        exe = os.path.join(os.getcwd(), "a.out") + +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        break1 = target.BreakpointCreateByLocation(self.main_source, self.line) +        self.assertTrue(break1, VALID_BREAKPOINT) + +        # Now launch the process, and do not stop at entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        self.assertTrue(process, PROCESS_IS_VALID) + +        # The stop reason of the thread should be breakpoint. +        thread = process.GetThreadAtIndex(0) +        if thread.GetStopReason() != lldb.eStopReasonBreakpoint: +            from lldbsuite.test.lldbutil import stop_reason_to_str +            self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS % +                      stop_reason_to_str(thread.GetStopReason())) + +        # Make sure we stopped at the first breakpoint. + +        cur_frame = thread.GetFrameAtIndex(0) + +        line_number = cur_frame.GetLineEntry().GetLine() +        self.assertTrue (line_number == self.line, "Hit the first breakpoint.") + +        my_var = cur_frame.FindVariable("my") +        self.assertTrue(my_var, "Made a variable object for my") + +        str_var = cur_frame.FindVariable("str") +        self.assertTrue(str_var, "Made a variable object for str") + +        # Now make sure that the my->str == str: + +        my_str_var = my_var.GetChildMemberWithName("str") +        self.assertTrue(my_str_var, "Found a str ivar in my") + +        str_value = int(str_var.GetValue(), 0) + +        my_str_value = int(my_str_var.GetValue(), 0) + +        self.assertTrue(str_value == my_str_value, "Got the correct value for my->str") + +    def test_expression_lookups_objc(self): +        """Test running an expression detect spurious debug info lookups (DWARF).""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # Stop at -[MyString initWithNSString:]. +        lldbutil.run_break_set_by_symbol (self, '-[MyString initWithNSString:]', num_expected_locations=1, sym_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) + +        global file_index +        # Log any DWARF lookups +        ++file_index +        logfile = os.path.join(os.getcwd(), "dwarf-lookups-" + self.getArchitecture() + "-" + str(file_index) + ".txt") +        self.runCmd("log enable -f %s dwarf lookups" % (logfile)) +        self.runCmd("expr self") +        self.runCmd("log disable dwarf lookups") +         +        def cleanup(): +            if os.path.exists (logfile): +                os.unlink (logfile) +         +        self.addTearDownHook(cleanup) +         +        if os.path.exists (logfile): +            f = open(logfile) +            lines = f.readlines() +            num_errors = 0 +            for line in lines: +                if string.find(line, "$__lldb") != -1: +                    if num_errors == 0: +                        print("error: found spurious name lookups when evaluating an expression:") +                    num_errors += 1 +                    print(line, end='') +            self.assertTrue(num_errors == 0, "Spurious lookups detected") +            f.close() diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods2.py b/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods2.py new file mode 100644 index 000000000000..b61a7702f1fe --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods2.py @@ -0,0 +1,169 @@ +""" +Test more expression command sequences with objective-c. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +@skipUnlessDarwin +class FoundationTestCase2(TestBase): + +    mydir = TestBase.compute_mydir(__file__) +     +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line numbers to break at. +        self.lines = [] +        self.lines.append(line_number('main.m', '// Break here for selector: tests')) +        self.lines.append(line_number('main.m', '// Break here for NSArray tests')) +        self.lines.append(line_number('main.m', '// Break here for NSString tests')) +        self.lines.append(line_number('main.m', '// Break here for description test')) +        self.lines.append(line_number('main.m', '// Set break point at this line')) + +    def test_more_expr_commands(self): +        """More expression commands for objective-c.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # Create a bunch of breakpoints. +        for line in self.lines: +            lldbutil.run_break_set_by_file_and_line (self, "main.m", line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) + +        # Test_Selector: +        self.runCmd("thread backtrace") +        self.expect("expression (char *)sel_getName(sel)", +            substrs = ["(char *)", +                       "length"]) + +        self.runCmd("process continue") + +        # Test_NSArray: +        self.runCmd("thread backtrace") +        self.runCmd("process continue") + +        # Test_NSString: +        self.runCmd("thread backtrace") +        self.runCmd("process continue") + +        # Test_MyString: +        self.runCmd("thread backtrace") +        self.expect("expression (char *)sel_getName(_cmd)", +            substrs = ["(char *)", +                       "description"]) + +        self.runCmd("process continue") + +    def test_NSArray_expr_commands(self): +        """Test expression commands for NSArray.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # Break inside Test_NSArray: +        line = self.lines[1] +        lldbutil.run_break_set_by_file_and_line (self, "main.m", line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) + +        # Test_NSArray: +        self.runCmd("thread backtrace") +        self.expect("expression (int)[nil_mutable_array count]", +            patterns = ["\(int\) \$.* = 0"]) +        self.expect("expression (int)[array1 count]", +            patterns = ["\(int\) \$.* = 3"]) +        self.expect("expression (int)[array2 count]", +            patterns = ["\(int\) \$.* = 3"]) +        self.expect("expression (int)array1.count", +            patterns = ["\(int\) \$.* = 3"]) +        self.expect("expression (int)array2.count", +            patterns = ["\(int\) \$.* = 3"]) +        self.runCmd("process continue") + +    def test_NSString_expr_commands(self): +        """Test expression commands for NSString.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # Break inside Test_NSString: +        line = self.lines[2] +        lldbutil.run_break_set_by_file_and_line (self, "main.m", line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) + +        # Test_NSString: +        self.runCmd("thread backtrace") +        self.expect("expression (int)[str length]", +            patterns = ["\(int\) \$.* ="]) +        self.expect("expression (int)[str_id length]", +            patterns = ["\(int\) \$.* ="]) +        self.expect("expression [str description]", +            patterns = ["\(id\) \$.* = 0x"]) +        self.expect("expression (id)[str_id description]", +            patterns = ["\(id\) \$.* = 0x"]) +        self.expect("expression str.length") +        self.expect("expression str.description") +        self.expect('expression str = @"new"') +        self.runCmd("image lookup -t NSString") +        self.expect('expression str = [NSString stringWithCString: "new"]') +        self.runCmd("process continue") + +    def test_MyString_dump(self): +        """Test dump of a known Objective-C object by dereferencing it.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) +         +        line = self.lines[4] + +        lldbutil.run_break_set_by_file_and_line (self, "main.m", line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) +         +        self.expect("expression --show-types -- *my", +            patterns = ["\(MyString\) \$.* = ", "\(MyBase\)", "\(NSObject\)", "\(Class\)"]) +        self.runCmd("process continue") + +    @expectedFailurei386 +    def test_NSError_po(self): +        """Test that po of the result of an unknown method doesn't require a cast.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) +         +        line = self.lines[4] + +        lldbutil.run_break_set_by_file_and_line (self, "main.m", line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) + +        self.expect('po [NSError errorWithDomain:@"Hello" code:35 userInfo:@{@"NSDescription" : @"be completed."}]', +            substrs = ["Error Domain=Hello", "Code=35", "be completed."]) +        self.runCmd("process continue") +         +    def test_NSError_p(self): +        """Test that p of the result of an unknown method does require a cast.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) +         +        line = self.lines[4] + +        lldbutil.run_break_set_by_file_and_line (self, "main.m", line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) + +        self.expect("p [NSError thisMethodIsntImplemented:0]", +                    error = True,  +                    patterns = ["no known method", "cast the message send to the method's return type"]) +        self.runCmd("process continue") diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjectDescriptionAPI.py b/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjectDescriptionAPI.py new file mode 100644 index 000000000000..a85f0fec9636 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjectDescriptionAPI.py @@ -0,0 +1,71 @@ +""" +Test SBValue.GetObjectDescription() with the value from SBTarget.FindGlobalVariables(). +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class ObjectDescriptionAPITestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break at. +        self.source = 'main.m' +        self.line = line_number(self.source, '// Set break point at this line.') + +    # rdar://problem/10857337 +    @skipUnlessDarwin +    @add_test_categories(['pyapi']) +    def test_find_global_variables_then_object_description(self): +        """Exercise SBTarget.FindGlobalVariables() API.""" +        d = {'EXE': 'b.out'} +        self.build(dictionary=d) +        self.setTearDownCleanup(dictionary=d) +        exe = os.path.join(os.getcwd(), 'b.out') + +        # Create a target by the debugger. +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        breakpoint = target.BreakpointCreateByLocation(self.source, self.line) +        self.assertTrue(breakpoint, VALID_BREAKPOINT) + +        # Now launch the process, and do not stop at entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) +        self.assertTrue(process, PROCESS_IS_VALID) +        # Make sure we hit our breakpoint: +        thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint) +        self.assertTrue (len(thread_list) == 1) + +        thread = thread_list[0] +        frame0 = thread.GetFrameAtIndex(0) + +        # Note my_global_str's object description prints fine here. +        value_list1 = frame0.GetVariables(True, True, True, True) +        for v in value_list1: +            self.DebugSBValue(v) +            if self.TraceOn(): +                print("val:", v) +                print("object description:", v.GetObjectDescription()) +            if v.GetName() == 'my_global_str': +                self.assertTrue(v.GetObjectDescription() == 'This is a global string') + +        # But not here! +        value_list2 = target.FindGlobalVariables('my_global_str', 3) +        for v in value_list2: +            self.DebugSBValue(v) +            if self.TraceOn(): +                print("val:", v) +                print("object description:", v.GetObjectDescription()) +            if v.GetName() == 'my_global_str': +                self.assertTrue(v.GetObjectDescription() == 'This is a global string') diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/TestRuntimeTypes.py b/packages/Python/lldbsuite/test/lang/objc/foundation/TestRuntimeTypes.py new file mode 100644 index 000000000000..8f191721d89b --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/TestRuntimeTypes.py @@ -0,0 +1,48 @@ +""" +Test that Objective-C methods from the runtime work correctly. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +@skipUnlessDarwin +class RuntimeTypesTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def test_break(self): +        """Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'.""" +        if self.getArchitecture() != 'x86_64': +            self.skipTest("This only applies to the v2 runtime") + +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # Stop at -[MyString description]. +        lldbutil.run_break_set_by_symbol (self, '-[MyString description]', num_expected_locations=1, sym_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) + +        # The backtrace should show we stop at -[MyString description]. +        self.expect("thread backtrace", "Stop at -[MyString description]", +            substrs = ["a.out`-[MyString description]"]) + +        # Use runtime information about NSString. + +        # The length property should be usable. +        self.expect("expression str.length", VARIABLES_DISPLAYED_CORRECTLY, +            patterns = [r"(\(unsigned long long\))|\(NSUInteger\)"]) + +        # Static methods on NSString should work. +        self.expect("expr [NSString stringWithCString:\"foo\" encoding:1]", VALID_TYPE, +            substrs = ["(id)", "$1"]) + +        self.expect("po $1", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["foo"]) diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/TestSymbolTable.py b/packages/Python/lldbsuite/test/lang/objc/foundation/TestSymbolTable.py new file mode 100644 index 000000000000..72952c1878b1 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/TestSymbolTable.py @@ -0,0 +1,68 @@ +""" +Test symbol table access for main.m. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * + +@skipUnlessDarwin +class FoundationSymtabTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    symbols_list = ['-[MyString initWithNSString:]', +                    '-[MyString dealloc]', +                    '-[MyString description]', +                    '-[MyString descriptionPauses]',     # synthesized property +                    '-[MyString setDescriptionPauses:]', # synthesized property +                    'Test_Selector', +                    'Test_NSString', +                    'Test_MyString', +                    'Test_NSArray', +                    'main' +                    ] + +    @add_test_categories(['pyapi']) +    def test_with_python_api(self): +        """Test symbol table access with Python APIs.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        # Launch the process, and do not stop at the entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        # +        # Exercise Python APIs to access the symbol table entries. +        # + +        # Create the filespec by which to locate our a.out module. +        filespec = lldb.SBFileSpec(exe, False) + +        module = target.FindModule(filespec) +        self.assertTrue(module, VALID_MODULE) + +        # Create the set of known symbols.  As we iterate through the symbol +        # table, remove the symbol from the set if it is a known symbol. +        expected_symbols = set(self.symbols_list) +        for symbol in module: +            self.assertTrue(symbol, VALID_SYMBOL) +            #print("symbol:", symbol) +            name = symbol.GetName() +            if name in expected_symbols: +                #print("Removing %s from known_symbols %s" % (name, expected_symbols)) +                expected_symbols.remove(name) + +        # At this point, the known_symbols set should have become an empty set. +        # If not, raise an error. +        #print("symbols unaccounted for:", expected_symbols) +        self.assertTrue(len(expected_symbols) == 0, +                        "All the known symbols are accounted for") diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/const-strings.m b/packages/Python/lldbsuite/test/lang/objc/foundation/const-strings.m new file mode 100644 index 000000000000..8a43abee7b84 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/const-strings.m @@ -0,0 +1,24 @@ +#import <Foundation/Foundation.h> + +// Tests to run: + +// Breakpoint 1 +// -- +// (lldb) expr (int)[str compare:@"hello"] +// (int) $0 = 0 +// (lldb) expr (int)[str compare:@"world"] +// (int) $1 = -1 +// (lldb) expr (int)[@"" length] +// (int) $2 = 0 + +int main () +{ +  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + +  NSString *str = [NSString stringWithCString:"hello" encoding:NSASCIIStringEncoding]; + +  NSLog(@"String \"%@\" has length %lu", str, [str length]); // Set breakpoint here. + +  [pool drain]; +  return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/main.m b/packages/Python/lldbsuite/test/lang/objc/foundation/main.m new file mode 100644 index 000000000000..519bec5a3e6a --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/main.m @@ -0,0 +1,141 @@ +#import <Foundation/Foundation.h> +#include <unistd.h> +#import "my-base.h" + +@interface MyString : MyBase { +    NSString *str; +    NSDate *date; +    BOOL _desc_pauses; +} + +@property(retain) NSString * str_property; +@property BOOL descriptionPauses; + +- (id)initWithNSString:(NSString *)string; +@end + +@implementation MyString +@synthesize descriptionPauses = _desc_pauses; +@synthesize str_property = str; + +- (id)initWithNSString:(NSString *)string +{ +    if (self = [super init]) +    { +        str = [NSString stringWithString:string]; +        date = [NSDate date]; +    } +    self.descriptionPauses = NO; +    return self; +} + +- (void)dealloc +{ +    [date release]; +    [str release]; +    [super dealloc]; +} + +- (NSString *)description +{ +    // Set a breakpoint on '-[MyString description]' and test expressions: +    // expression (char *)sel_getName(_cmd) +  if (self.descriptionPauses)  // Break here for description test +    { +        printf ("\nAbout to sleep.\n"); +        usleep(100000); +    } + +    return [str stringByAppendingFormat:@" with timestamp: %@", date]; +} +@end + +int +Test_Selector () +{ +    SEL sel = @selector(length); +    printf("sel = %p\n", sel); +    // Expressions to test here for selector:  +    // expression (char *)sel_getName(sel) +    //      The expression above should return "sel" as it should be just +    //      a uniqued C string pointer. We were seeing the result pointer being +    //      truncated with recent LLDBs. +    return 0; // Break here for selector: tests +} + +int +Test_NSString (const char *program) +{ +    NSString *str = [NSString stringWithFormat:@"Hello from '%s'", program]; +    NSLog(@"NSString instance: %@", str); +    printf("str = '%s'\n", [str cStringUsingEncoding: [NSString defaultCStringEncoding]]); +    printf("[str length] = %zu\n", (size_t)[str length]); +    printf("[str description] = %s\n", [[str description] UTF8String]); +    id str_id = str; +    // Expressions to test here for NSString: +    // expression (char *)sel_getName(sel) +    // expression [str length] +    // expression [str_id length] +    // expression [str description] +    // expression [str_id description] +    // expression str.length +    // expression str.description +    // expression str = @"new" +    // expression str = [NSString stringWithFormat: @"%cew", 'N'] +    return 0; // Break here for NSString tests +} + +NSString *my_global_str = NULL; + +void +Test_MyString (const char *program) +{ +    my_global_str = @"This is a global string"; +    NSString *str = [NSString stringWithFormat:@"Hello from '%s'", program]; +    MyString *my = [[MyString alloc] initWithNSString:str]; +    NSLog(@"MyString instance: %@", [my description]); +    my.descriptionPauses = YES;     // Set break point at this line.  Test 'expression -o -- my'. +    NSLog(@"MyString instance: %@", [my description]); +} + +int +Test_NSArray () +{ +    NSMutableArray *nil_mutable_array = nil; +    NSArray *array1 = [NSArray arrayWithObjects: @"array1 object1", @"array1 object2", @"array1 object3", nil]; +    NSArray *array2 = [NSArray arrayWithObjects: array1, @"array2 object2", @"array2 object3", nil]; +    // Expressions to test here for NSArray: +    // expression [nil_mutable_array count] +    // expression [array1 count] +    // expression array1.count +    // expression [array2 count] +    // expression array2.count +    id obj; +    // After each object at index call, use expression and validate object +    obj = [array1 objectAtIndex: 0]; // Break here for NSArray tests +    obj = [array1 objectAtIndex: 1]; +    obj = [array1 objectAtIndex: 2]; + +    obj = [array2 objectAtIndex: 0]; +    obj = [array2 objectAtIndex: 1]; +    obj = [array2 objectAtIndex: 2]; +    NSUInteger count = [nil_mutable_array count]; +    return 0; +} + + +int main (int argc, char const *argv[]) +{ +    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +    Test_Selector(); +    Test_NSArray (); +    Test_NSString (argv[0]); +    Test_MyString (argv[0]); + +    printf("sizeof(id) = %zu\n", sizeof(id)); +    printf("sizeof(Class) = %zu\n", sizeof(Class)); +    printf("sizeof(SEL) = %zu\n", sizeof(SEL)); + +    [pool release]; +    return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/my-base.h b/packages/Python/lldbsuite/test/lang/objc/foundation/my-base.h new file mode 100644 index 000000000000..53202aa0de37 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/my-base.h @@ -0,0 +1,8 @@ +@interface MyBase : NSObject  +{ +#if !__OBJC2__ +  int maybe_used; // The 1.0 runtime needs to have backed properties... +#endif +} +@property int propertyMovesThings; +@end diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/my-base.m b/packages/Python/lldbsuite/test/lang/objc/foundation/my-base.m new file mode 100644 index 000000000000..0c316b244f26 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/my-base.m @@ -0,0 +1,10 @@ +#import <Foundation/Foundation.h> +#import "my-base.h" +@implementation MyBase +#if __OBJC2__ +@synthesize propertyMovesThings; +#else +@synthesize propertyMovesThings = maybe_used; +#endif +@end + diff --git a/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/InternalDefiner.h b/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/InternalDefiner.h new file mode 100644 index 000000000000..59652d4b09c0 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/InternalDefiner.h @@ -0,0 +1,11 @@ +#import <Foundation/Foundation.h> +#import <stdint.h> + +@interface InternalDefiner : NSObject { +@public +    uintptr_t foo; +} + +-(id)initWithFoo:(uintptr_t)f andBar:(uintptr_t)b; + +@end diff --git a/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/InternalDefiner.m b/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/InternalDefiner.m new file mode 100644 index 000000000000..1a10ce021ce3 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/InternalDefiner.m @@ -0,0 +1,31 @@ +#import "InternalDefiner.h" + +@interface InternalDefiner () { +    uintptr_t bar; +} + +@end + +@implementation InternalDefiner + +-(id)init +{ +    if (self = [super init]) +    { +        foo = 2; +        bar = 3; +    } +    return self; +} + +-(id)initWithFoo:(uintptr_t)f andBar:(uintptr_t)b +{ +    if (self = [super init]) +    { +        foo = f; +        bar = b; +    } +    return self; +} + +@end diff --git a/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/Makefile b/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/Makefile new file mode 100644 index 000000000000..1768d11ca279 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +DYLIB_NAME := InternalDefiner +DYLIB_OBJC_SOURCES := InternalDefiner.m +OBJC_SOURCES := main.m + +LD_EXTRAS = -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/TestHiddenIvars.py b/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/TestHiddenIvars.py new file mode 100644 index 000000000000..e85dd8f48dec --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/TestHiddenIvars.py @@ -0,0 +1,174 @@ +"""Test that hidden ivars in a shared library are visible from the main executable.""" + +from __future__ import print_function + + + +import unittest2 +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil +import subprocess + +class HiddenIvarsTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break inside main(). +        self.source = 'main.m' +        self.line = line_number(self.source, '// breakpoint1') +        # The makefile names of the shared libraries as they appear in DYLIB_NAME. +        # The names should have no loading "lib" or extension as they will be localized +        self.shlib_names = ["InternalDefiner"] + +    @skipUnlessDarwin +    @skipIfDwarf    # This test requires a stripped binary and a dSYM +    @skipIfDWO      # This test requires a stripped binary and a dSYM +    def test_expr_stripped(self): +        if self.getArchitecture() == 'i386': +            self.skipTest("requires modern objc runtime") +        else: +            self.build() +            self.expr(True) + +    @skipUnlessDarwin +    def test_expr(self): +        if self.getArchitecture() == 'i386': +            self.skipTest("requires modern objc runtime") +        else: +            self.build() +            self.expr(False) + +    @skipUnlessDarwin +    @skipIfDwarf    # This test requires a stripped binary and a dSYM +    @skipIfDWO      # This test requires a stripped binary and a dSYM +    def test_frame_variable_stripped(self): +        if self.getArchitecture() == 'i386': +            self.skipTest("requires modern objc runtime") +        else: +            self.build() +            self.frame_var(True) + +    @skipUnlessDarwin +    def test_frame_variable(self): +        if self.getArchitecture() == 'i386': +            self.skipTest("requires modern objc runtime") +        else: +            self.build() +            self.frame_var(False) + +    @unittest2.expectedFailure("rdar://18683637") +    @skipUnlessDarwin +    def test_frame_variable_across_modules(self): +        if self.getArchitecture() == 'i386': +            self.skipTest("requires modern objc runtime") +        else: +            self.build() +            self.common_setup(False) +            self.expect("frame variable k->bar", VARIABLES_DISPLAYED_CORRECTLY, substrs = ["= 3"]) +         +    def common_setup(self, strip): +         +        if strip: +            self.assertTrue(subprocess.call(['/usr/bin/strip', '-Sx', 'libInternalDefiner.dylib']) == 0, 'stripping dylib succeeded') +            self.assertTrue(subprocess.call(['/bin/rm', '-rf', 'libInternalDefiner.dylib.dSYM']) == 0, 'remove dylib dSYM file succeeded') +            self.assertTrue(subprocess.call(['/usr/bin/strip', '-Sx', 'a.out']) == 0, 'stripping a.out succeeded') +        # Create a target by the debugger. +        target = self.dbg.CreateTarget("a.out") +        self.assertTrue(target, VALID_TARGET) + +        # Create the breakpoint inside function 'main'. +        breakpoint = target.BreakpointCreateByLocation(self.source, self.line) +        self.assertTrue(breakpoint, VALID_BREAKPOINT) +         +        # Register our shared libraries for remote targets so they get automatically uploaded +        environment = self.registerSharedLibrariesWithTarget(target, self.shlib_names) + +        # Now launch the process, and do not stop at entry point. +        process = target.LaunchSimple (None, environment, self.get_process_working_directory()) +        self.assertTrue(process, PROCESS_IS_VALID) +         +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # Break inside the foo function which takes a bar_ptr argument. +        lldbutil.run_break_set_by_file_and_line (self, "main.m", self.line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) + +        # The stop reason of the thread should be breakpoint. +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +            substrs = ['stopped', +                       'stop reason = breakpoint']) + +        # The breakpoint should have a hit count of 1. +        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, +            substrs = [' resolved, hit count = 1']) + +    def expr(self, strip): +        self.common_setup(strip) + +        # This should display correctly. +        self.expect("expression (j->_definer->foo)", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["= 4"]) + +        self.expect("expression (j->_definer->bar)", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["= 5"]) + +        if strip: +            self.expect("expression *(j->_definer)", VARIABLES_DISPLAYED_CORRECTLY, +                substrs = ["foo = 4"]) +        else: +            self.expect("expression *(j->_definer)", VARIABLES_DISPLAYED_CORRECTLY, +                substrs = ["foo = 4", "bar = 5"]) + +        self.expect("expression (k->foo)", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["= 2"]) + +        self.expect("expression (k->bar)", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["= 3"]) + +        self.expect("expression k.filteredDataSource", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = [' = 0x', '"2 elements"']) + +        if strip: +            self.expect("expression *(k)", VARIABLES_DISPLAYED_CORRECTLY, +                substrs = ["foo = 2", ' = 0x', '"2 elements"']) +        else:             +            self.expect("expression *(k)", VARIABLES_DISPLAYED_CORRECTLY, +                substrs = ["foo = 2", "bar = 3", '_filteredDataSource = 0x', '"2 elements"']) + +    def frame_var(self, strip): +        self.common_setup(strip) + +        # This should display correctly. +        self.expect("frame variable j->_definer->foo", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["= 4"]) + +        if not strip: +            self.expect("frame variable j->_definer->bar", VARIABLES_DISPLAYED_CORRECTLY, +                substrs = ["= 5"]) +             +        if strip: +            self.expect("frame variable *j->_definer", VARIABLES_DISPLAYED_CORRECTLY, +                substrs = ["foo = 4"]) +        else: +            self.expect("frame variable *j->_definer", VARIABLES_DISPLAYED_CORRECTLY, +                substrs = ["foo = 4", "bar = 5"]) + +        self.expect("frame variable k->foo", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["= 2"]) + +        self.expect("frame variable k->_filteredDataSource", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = [' = 0x', '"2 elements"']) + +        if strip: +            self.expect("frame variable *k", VARIABLES_DISPLAYED_CORRECTLY, +                substrs = ["foo = 2", '_filteredDataSource = 0x', '"2 elements"']) +        else: +            self.expect("frame variable *k", VARIABLES_DISPLAYED_CORRECTLY, +                substrs = ["foo = 2", "bar = 3", '_filteredDataSource = 0x', '"2 elements"']) diff --git a/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/main.m b/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/main.m new file mode 100644 index 000000000000..1795d56e7d8a --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/main.m @@ -0,0 +1,54 @@ +#import <Foundation/Foundation.h> +#import "InternalDefiner.h" + +@interface Container : NSObject { +@public +    InternalDefiner *_definer; +} + +-(id)init; +@end + +@implementation Container + +-(id)init +{ +    if (self = [super init]) +    { +        _definer = [[InternalDefiner alloc] initWithFoo:4 andBar:5]; +    } +    return self; +} + +@end + +@interface InheritContainer : InternalDefiner  +@property (nonatomic, strong) NSMutableArray *filteredDataSource; +-(id)init; +@end + +@implementation InheritContainer + +-(id)init +{ +    if (self = [super initWithFoo:2 andBar:3]) +    { +        self.filteredDataSource = [NSMutableArray arrayWithObjects:@"hello", @"world", nil]; +    } +    return self; +} + +@end + +int main(int argc, const char * argv[]) +{ +    @autoreleasepool { +        Container *j = [[Container alloc] init]; +        InheritContainer *k = [[InheritContainer alloc] init]; + +        printf("ivar value = %u\n", (unsigned)j->_definer->foo); // breakpoint1 +        printf("ivar value = %u\n", (unsigned)k->foo); +    }    +    return 0; +} + diff --git a/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/Makefile b/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/Makefile new file mode 100644 index 000000000000..329ceabeea97 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/Makefile @@ -0,0 +1,12 @@ +LEVEL = ../../../make + +myclass.o: myclass.h myclass.m +	$(CC) myclass.m -c -o myclass.o + +repro: myclass.o repro.m +	$(CC) -g -O0 myclass.o repro.m -framework Foundation + +cleanup: +	rm -r myclass.o + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/TestObjCiVarIMP.py b/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/TestObjCiVarIMP.py new file mode 100644 index 000000000000..9ed2bb98e6e1 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/TestObjCiVarIMP.py @@ -0,0 +1,63 @@ +""" +Test that dynamically discovered ivars of type IMP do not crash LLDB +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * +import lldbsuite.support.seven as seven + +def execute_command (command): +    # print('%% %s' % (command)) +    (exit_status, output) = seven.get_command_status_output(command) +    # if output: +    #     print(output) +    # print('status = %u' % (exit_status)) +    return exit_status + +class ObjCiVarIMPTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    @skipUnlessDarwin +    @no_debug_info_test +    def test_imp_ivar_type(self): +        """Test that dynamically discovered ivars of type IMP do not crash LLDB""" +        if self.getArchitecture() == 'i386': +            # rdar://problem/9946499 +            self.skipTest("Dynamic types for ObjC V1 runtime not implemented") +         +        execute_command("make repro") +        def cleanup(): +            execute_command("make cleanup") +        self.addTearDownHook(cleanup) + +        exe = os.path.join(os.getcwd(), "a.out") + +        # Create a target from the debugger. +        target = self.dbg.CreateTarget (exe) +        self.assertTrue(target, VALID_TARGET) + +        # Set up our breakpoint + +        bkpt = lldbutil.run_break_set_by_source_regexp (self, "break here") + +        # Now launch the process, and do not stop at the entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        self.assertTrue(process.GetState() == lldb.eStateStopped, +                        PROCESS_STOPPED) + +        self.expect('frame variable --ptr-depth=1 --show-types -d run -- object', substrs=[ +            '(MyClass *) object = 0x', +            '(void *) myImp = 0x' +        ]) +        self.expect('disassemble --start-address `((MyClass*)object)->myImp`', substrs=[ +            '-[MyClass init]' +        ]) diff --git a/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/myclass.h b/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/myclass.h new file mode 100644 index 000000000000..da28d1e05181 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/myclass.h @@ -0,0 +1,6 @@ +#import <Foundation/Foundation.h> + +@interface MyClass : NSObject +{} +- (id)init; +@end diff --git a/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/myclass.m b/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/myclass.m new file mode 100644 index 000000000000..85b2fcfe9b3c --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/myclass.m @@ -0,0 +1,16 @@ +#import <Foundation/Foundation.h> +#import "myclass.h" + +@implementation MyClass +{ +  IMP myImp; +} +- (id)init { +  if (self = [super init]) +  { +    SEL theSelector = @selector(init); +    self->myImp = [self methodForSelector:theSelector];  +  } +  return self; +} +@end diff --git a/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/repro.m b/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/repro.m new file mode 100644 index 000000000000..14f911f07dd8 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/repro.m @@ -0,0 +1,7 @@ +#import <Foundation/Foundation.h> +#import "myclass.h" + +int main() { +  id object = [MyClass new]; +  return 0; // break here +} diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-auto-import/Makefile b/packages/Python/lldbsuite/test/lang/objc/modules-auto-import/Makefile new file mode 100644 index 000000000000..e42b59f9518c --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/modules-auto-import/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make +OBJC_SOURCES := main.m + +CFLAGS += -fmodules -gmodules -g + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-auto-import/TestModulesAutoImport.py b/packages/Python/lldbsuite/test/lang/objc/modules-auto-import/TestModulesAutoImport.py new file mode 100644 index 000000000000..2c052aae3ba1 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/modules-auto-import/TestModulesAutoImport.py @@ -0,0 +1,53 @@ +"""Test that importing modules in Objective-C works as expected.""" + +from __future__ import print_function + + + +import unittest2 +import os, time +import lldb +import platform +import lldbsuite.test.lldbutil as lldbutil + +from distutils.version import StrictVersion + +from lldbsuite.test.lldbtest import * + +class ObjCModulesAutoImportTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break inside main(). +        self.line = line_number('main.m', '// Set breakpoint 0 here.') + +    @skipUnlessDarwin +    @unittest2.expectedFailure("rdar://problem/19991953") +    @expectedFailureDarwin # clang: error: unknown argument: '-gmodules' +    @unittest2.skipIf(platform.system() != "Darwin" or StrictVersion('12.0.0') > platform.release(), "Only supported on Darwin 12.0.0+") +    def test_expr(self): +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # Break inside the foo function which takes a bar_ptr argument. +        lldbutil.run_break_set_by_file_and_line (self, "main.m", self.line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) + +        # The stop reason of the thread should be breakpoint. +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +            substrs = ['stopped', +                       'stop reason = breakpoint']) + +        # The breakpoint should have a hit count of 1. +        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, +            substrs = [' resolved, hit count = 1']) + +        self.runCmd("settings set target.auto-import-clang-modules true") + +        self.expect("p getpid()", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["pid_t"]) diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-auto-import/main.m b/packages/Python/lldbsuite/test/lang/objc/modules-auto-import/main.m new file mode 100644 index 000000000000..5452ffd9bd15 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/modules-auto-import/main.m @@ -0,0 +1,7 @@ +@import Darwin; + +int main() +{ +    size_t ret = printf("Stop here\n"); // Set breakpoint 0 here. +    return ret; +} diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/Makefile b/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/Makefile new file mode 100644 index 000000000000..cbd95de007d8 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m myModule.m + +include $(LEVEL)/Makefile.rules + +CFLAGS += -fmodules -I$(PWD) +LDFLAGS += -framework Foundation diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/TestIncompleteModules.py b/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/TestIncompleteModules.py new file mode 100644 index 000000000000..8667e628d464 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/TestIncompleteModules.py @@ -0,0 +1,61 @@ +"""Test that DWARF types are trusted over module types""" + +from __future__ import print_function + + + +import unittest2 +import os, time +import lldb +import platform +import lldbsuite.test.lldbutil as lldbutil + +from distutils.version import StrictVersion + +from lldbsuite.test.lldbtest import * + +class IncompleteModulesTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break inside main(). +        self.line = line_number('main.m', '// Set breakpoint 0 here.') + +    @skipUnlessDarwin +    @unittest2.expectedFailure("rdar://20416388") +    @unittest2.skipIf(platform.system() != "Darwin" or StrictVersion('12.0.0') > platform.release(), "Only supported on Darwin 12.0.0+") +    def test_expr(self): +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # Break inside the foo function which takes a bar_ptr argument. +        lldbutil.run_break_set_by_file_and_line (self, "main.m", self.line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) + +        # The stop reason of the thread should be breakpoint. +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +            substrs = ['stopped', +                       'stop reason = breakpoint']) + +        # The breakpoint should have a hit count of 1. +        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, +            substrs = [' resolved, hit count = 1']) + +        self.runCmd("settings set target.clang-module-search-paths \"" + os.getcwd() + "\"") + +        self.expect("expr @import myModule; 3", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["int", "3"]) + +        self.expect("expr [myObject privateMethod]", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["int", "5"]) + +        self.expect("expr MIN(2,3)", "#defined macro was found", +            substrs = ["int", "2"]) + +        self.expect("expr MAX(2,3)", "#undefd macro was correcltly not found", +            error=True) diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/main.m b/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/main.m new file mode 100644 index 000000000000..8ebfb0c1f11a --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/main.m @@ -0,0 +1,11 @@ +@import Foundation; +@import myModule; + +int main() +{ +    @autoreleasepool +    { +        MyClass *myObject = [MyClass alloc]; +        [myObject publicMethod]; // Set breakpoint 0 here. +    } +} diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/module.map b/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/module.map new file mode 100644 index 000000000000..2ef8064d15b4 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/module.map @@ -0,0 +1,4 @@ +module myModule { +  header "myModule.h" +  export * +} diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/myModule.h b/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/myModule.h new file mode 100644 index 000000000000..d03dde0d07aa --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/myModule.h @@ -0,0 +1,8 @@ +@import Foundation; + +#undef MAX + +@interface MyClass : NSObject { +}; +-(void)publicMethod; +@end diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/myModule.m b/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/myModule.m new file mode 100644 index 000000000000..d6a2619d8016 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/myModule.m @@ -0,0 +1,14 @@ +#include "myModule.h" +#include "stdio.h" + +@implementation MyClass { +}; +-(void)publicMethod { +  printf("Hello public!\n"); +} +-(int)privateMethod { +  printf("Hello private!\n"); +  return 5; +} +@end + diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/Makefile b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/Makefile new file mode 100644 index 000000000000..6ad9e0010bb0 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +C_SOURCES := myModule.c + +OBJC_SOURCES := main.m + +include $(LEVEL)/Makefile.rules + +CFLAGS += -fmodules -I$(PWD) diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py new file mode 100644 index 000000000000..d9d94a8cf321 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py @@ -0,0 +1,55 @@ +"""Test that inline functions from modules are imported correctly""" + +from __future__ import print_function + + + +import unittest2 +import os, time +import lldb +import platform +import lldbsuite.test.lldbutil as lldbutil + +from distutils.version import StrictVersion + +from lldbsuite.test.lldbtest import * + +class ModulesInlineFunctionsTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break inside main(). +        self.line = line_number('main.m', '// Set breakpoint here.') + +    @skipUnlessDarwin +    @unittest2.skipIf(platform.system() != "Darwin" or StrictVersion('12.0.0') > platform.release(), "Only supported on Darwin 12.0.0+") +    @expectedFailureDarwin("llvm.org/pr25743") +    def test_expr(self): +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # Break inside the foo function which takes a bar_ptr argument. +        lldbutil.run_break_set_by_file_and_line (self, "main.m", self.line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) + +        # The stop reason of the thread should be breakpoint. +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +            substrs = ['stopped', +                       'stop reason = breakpoint']) + +        # The breakpoint should have a hit count of 1. +        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, +            substrs = [' resolved, hit count = 1']) + +        self.runCmd("settings set target.clang-module-search-paths \"" + os.getcwd() + "\"") + +        self.expect("expr @import myModule; 3", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["int", "3"]) + +        self.expect("expr isInline(2)", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["4"]) diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/main.m b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/main.m new file mode 100644 index 000000000000..13a5bf316ee9 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/main.m @@ -0,0 +1,9 @@ +@import Darwin; +@import myModule; + +int main() +{ +    int a = isInline(2); +    int b = notInline(); +    printf("%d %d\n", a, b); // Set breakpoint here. +} diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/module.map b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/module.map new file mode 100644 index 000000000000..2ef8064d15b4 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/module.map @@ -0,0 +1,4 @@ +module myModule { +  header "myModule.h" +  export * +} diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/myModule.c b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/myModule.c new file mode 100644 index 000000000000..ad3c85d155e4 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/myModule.c @@ -0,0 +1,7 @@ +#include "myModule.h" + +int notInline() +{ +    return 3; +} + diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/myModule.h b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/myModule.h new file mode 100644 index 000000000000..d50d0101f645 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/myModule.h @@ -0,0 +1,7 @@ +int notInline(); + +static __inline__ __attribute__ ((always_inline)) int isInline(int a) +{ +    int b = a + a; +    return b; +} diff --git a/packages/Python/lldbsuite/test/lang/objc/modules/Makefile b/packages/Python/lldbsuite/test/lang/objc/modules/Makefile new file mode 100644 index 000000000000..ad3cb3fadcde --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/modules/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation diff --git a/packages/Python/lldbsuite/test/lang/objc/modules/TestObjCModules.py b/packages/Python/lldbsuite/test/lang/objc/modules/TestObjCModules.py new file mode 100644 index 000000000000..04fc07281811 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/modules/TestObjCModules.py @@ -0,0 +1,71 @@ +"""Test that importing modules in Objective-C works as expected.""" + +from __future__ import print_function + + + +import unittest2 +import os, time +import lldb +import platform +import lldbsuite.test.lldbutil as lldbutil + +from distutils.version import StrictVersion + +from lldbsuite.test.lldbtest import * + +class ObjCModulesTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break inside main(). +        self.line = line_number('main.m', '// Set breakpoint 0 here.') + +    @skipUnlessDarwin +    @unittest2.expectedFailure("rdar://20416388") +    @unittest2.skipIf(platform.system() != "Darwin" or StrictVersion('12.0.0') > platform.release(), "Only supported on Darwin 12.0.0+") +    def test_expr(self): +        if not self.applies(): +            return + +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # Break inside the foo function which takes a bar_ptr argument. +        lldbutil.run_break_set_by_file_and_line (self, "main.m", self.line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) + +        # The stop reason of the thread should be breakpoint. +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +            substrs = ['stopped', +                       'stop reason = breakpoint']) + +        # The breakpoint should have a hit count of 1. +        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, +            substrs = [' resolved, hit count = 1']) + +        self.expect("expr @import Darwin; 3", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["int", "3"]) + +        self.expect("expr getpid()", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["pid_t"]) + +        self.expect("expr @import Foundation; 4", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["int", "4"]) + +        self.expect("expr string.length", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["NSUInteger", "5"]) + +        self.expect("expr array.count", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["NSUInteger", "3"]) + +        self.expect("p *[NSURL URLWithString:@\"http://lldb.llvm.org\"]", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["NSURL", "isa", "_urlString"]) + +        self.expect("p [NSURL URLWithString:@\"http://lldb.llvm.org\"].scheme", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["http"]) diff --git a/packages/Python/lldbsuite/test/lang/objc/modules/main.m b/packages/Python/lldbsuite/test/lang/objc/modules/main.m new file mode 100644 index 000000000000..99b50f9620d6 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/modules/main.m @@ -0,0 +1,12 @@ +#import <Foundation/Foundation.h> + +int main() +{ +    @autoreleasepool +    { +        NSString *string = @"Hello"; +        NSArray *array = @[ @1, @2, @3 ]; + +        NSLog(@"Stop here"); // Set breakpoint 0 here. +    } +} diff --git a/packages/Python/lldbsuite/test/lang/objc/objc++/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc++/Makefile new file mode 100644 index 000000000000..910d4943ef05 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc++/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJCXX_SOURCES := main.mm +LD_EXTRAS = -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/objc++/TestObjCXX.py b/packages/Python/lldbsuite/test/lang/objc/objc++/TestObjCXX.py new file mode 100644 index 000000000000..38ef853ae112 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc++/TestObjCXX.py @@ -0,0 +1,33 @@ +""" +Make sure that ivars of Objective-C++ classes are visible in LLDB. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class ObjCXXTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    @skipUnlessDarwin +    def test_break(self): +        """Test ivars of Objective-C++ classes""" +        if self.getArchitecture() == 'i386': +            self.skipTest("requires Objective-C 2.0 runtime") + +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        lldbutil.run_break_set_by_source_regexp (self, 'breakpoint 1', num_expected_locations=1)  + +        self.runCmd("run", RUN_SUCCEEDED) + +        self.expect("expr f->f", "Found ivar in class", +            substrs = ["= 3"]) diff --git a/packages/Python/lldbsuite/test/lang/objc/objc++/main.mm b/packages/Python/lldbsuite/test/lang/objc/objc++/main.mm new file mode 100644 index 000000000000..50d2f0a8df37 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc++/main.mm @@ -0,0 +1,19 @@ +#include <Foundation/NSObject.h> + +@interface F : NSObject +@end + +@implementation F +{ +@public +    int f; +} + +@end + +int main(int argc, char* argv[]) +{ +    F* f = [F new]; +    f->f = 3; +    return 0; // breakpoint 1 +} diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-baseclass-sbtype/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-baseclass-sbtype/Makefile new file mode 100644 index 000000000000..7f7baeb3cf1c --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-baseclass-sbtype/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m +LD_EXTRAS = -lobjc -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-baseclass-sbtype/TestObjCBaseClassSBType.py b/packages/Python/lldbsuite/test/lang/objc/objc-baseclass-sbtype/TestObjCBaseClassSBType.py new file mode 100644 index 000000000000..5d2414eed8f5 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-baseclass-sbtype/TestObjCBaseClassSBType.py @@ -0,0 +1,58 @@ +""" +Use lldb Python API to test base class resolution for ObjC classes +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class ObjCDynamicValueTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp().                                                                                                            +        TestBase.setUp(self) + +        self.line = line_number('main.m', '// Set breakpoint here.') + +    @skipUnlessDarwin +    @add_test_categories(['pyapi']) +    def test_get_baseclass(self): +        """Test fetching ObjC dynamic values.""" +        if self.getArchitecture() == 'i386': +            # rdar://problem/9946499 +            self.skipTest("Dynamic types for ObjC V1 runtime not implemented") + +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        # Create a target from the debugger. + +        target = self.dbg.CreateTarget (exe) +        self.assertTrue(target, VALID_TARGET) + +        # Set up our breakpoints: + +        target.BreakpointCreateByLocation('main.m', self.line) +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        self.assertTrue(process.GetState() == lldb.eStateStopped, +                        PROCESS_STOPPED) + +        var = self.frame().FindVariable("foo") +        var_ptr_type = var.GetType() +        var_pte_type = var_ptr_type.GetPointeeType() +        self.assertTrue(var_ptr_type.GetNumberOfDirectBaseClasses() == 1, "Foo * has one base class") +        self.assertTrue(var_pte_type.GetNumberOfDirectBaseClasses() == 1, "Foo has one base class") + +        self.assertTrue(var_ptr_type.GetDirectBaseClassAtIndex(0).IsValid(), "Foo * has a valid base class") +        self.assertTrue(var_pte_type.GetDirectBaseClassAtIndex(0).IsValid(), "Foo * has a valid base class") + +        self.assertTrue(var_ptr_type.GetDirectBaseClassAtIndex(0).GetName() == var_pte_type.GetDirectBaseClassAtIndex(0).GetName(), "Foo and its pointer type don't agree on their base class") diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-baseclass-sbtype/main.m b/packages/Python/lldbsuite/test/lang/objc/objc-baseclass-sbtype/main.m new file mode 100644 index 000000000000..3ec78fd0bd6b --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-baseclass-sbtype/main.m @@ -0,0 +1,22 @@ +#import <Foundation/Foundation.h> + +@interface Foo : NSObject {} + +-(id) init; + +@end + +@implementation Foo + +-(id) init +{ +    return self = [super init]; +} +@end +int main () +{ +    Foo *foo = [Foo new]; +	NSLog(@"a"); // Set breakpoint here. +	return 0; +} + diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-builtin-types/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-builtin-types/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-builtin-types/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-builtin-types/TestObjCBuiltinTypes.py b/packages/Python/lldbsuite/test/lang/objc/objc-builtin-types/TestObjCBuiltinTypes.py new file mode 100644 index 000000000000..f7ce2809081a --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-builtin-types/TestObjCBuiltinTypes.py @@ -0,0 +1,55 @@ +"""Test that the expression parser doesn't get confused by 'id' and 'Class'""" + +from __future__ import print_function + + + +import os, time +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class TestObjCBuiltinTypes(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line numbers to break inside main(). +        self.main_source = "main.cpp" +        self.break_line = line_number(self.main_source, '// Set breakpoint here.') + +    @skipUnlessDarwin +    @add_test_categories(['pyapi']) +    #<rdar://problem/10591460> [regression] Can't print ivar value: error: reference to 'id' is ambiguous +    def test_with_python_api(self): +        """Test expression parser respect for ObjC built-in types.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        bpt = target.BreakpointCreateByLocation(self.main_source, self.break_line) +        self.assertTrue(bpt, VALID_BREAKPOINT) + +        # Now launch the process, and do not stop at entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        self.assertTrue(process, PROCESS_IS_VALID) + +        # The stop reason of the thread should be breakpoint. +        thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, bpt) + +        # Make sure we stopped at the first breakpoint. +        self.assertTrue (len(thread_list) != 0, "No thread stopped at our breakpoint.") +        self.assertTrue (len(thread_list) == 1, "More than one thread stopped at our breakpoint.") +             +        # Now make sure we can call a function in the class method we've stopped in. +        frame = thread_list[0].GetFrameAtIndex(0) +        self.assertTrue (frame, "Got a valid frame 0 frame.") + +        self.expect("expr (foo)", patterns = ["\(ns::id\) \$.* = 0"]) + +        self.expect("expr id my_id = 0; my_id", patterns = ["\(id\) \$.* = nil"]) diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-builtin-types/main.cpp b/packages/Python/lldbsuite/test/lang/objc/objc-builtin-types/main.cpp new file mode 100644 index 000000000000..6dd8cbc6e9fe --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-builtin-types/main.cpp @@ -0,0 +1,9 @@ +namespace ns { +  typedef int id; +}; + +int main() +{ +  ns::id foo = 0; +  return foo; // Set breakpoint here. +} diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-checker/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-checker/Makefile new file mode 100644 index 000000000000..a1608fe5a664 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-checker/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-checker/TestObjCCheckers.py b/packages/Python/lldbsuite/test/lang/objc/objc-checker/TestObjCCheckers.py new file mode 100644 index 000000000000..533ec2f6b7c4 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-checker/TestObjCCheckers.py @@ -0,0 +1,75 @@ +""" +Use lldb Python API to make sure the dynamic checkers are doing their jobs. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class ObjCCheckerTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp().                                                                                                            +        TestBase.setUp(self) + +        # Find the line number to break for main.c.                                                                                        +        self.source_name = 'main.m' + +    @skipUnlessDarwin +    @add_test_categories(['pyapi']) +    def test_objc_checker(self): +        """Test that checkers catch unrecognized selectors""" +        if self.getArchitecture() == 'i386': +            self.skipTest("requires Objective-C 2.0 runtime") + +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        # Create a target from the debugger. + +        target = self.dbg.CreateTarget (exe) +        self.assertTrue(target, VALID_TARGET) + +        # Set up our breakpoints: + +         +        main_bkpt = target.BreakpointCreateBySourceRegex ("Set a breakpoint here.", lldb.SBFileSpec (self.source_name)) +        self.assertTrue(main_bkpt and +                        main_bkpt.GetNumLocations() == 1, +                        VALID_BREAKPOINT) + +        # Now launch the process, and do not stop at the entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        self.assertTrue(process.GetState() == lldb.eStateStopped, +                        PROCESS_STOPPED) + +        threads = lldbutil.get_threads_stopped_at_breakpoint (process, main_bkpt) +        self.assertTrue (len(threads) == 1) +        thread = threads[0] + +        # +        #  The class Simple doesn't have a count method.  Make sure that we don't  +        #  actually try to send count but catch it as an unrecognized selector. + +        frame = thread.GetFrameAtIndex(0) +        expr_value = frame.EvaluateExpression("(int) [my_simple count]", False) +        expr_error = expr_value.GetError() + +        self.assertTrue (expr_error.Fail()) +         +        # Make sure the call produced no NSLog stdout. +        stdout = process.GetSTDOUT(100) +        self.assertTrue (stdout is None or (len(stdout) == 0)) +         +        # Make sure the error is helpful: +        err_string = expr_error.GetCString() +        self.assertTrue ("selector" in err_string) diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-checker/main.m b/packages/Python/lldbsuite/test/lang/objc/objc-checker/main.m new file mode 100644 index 000000000000..4a09a2826f70 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-checker/main.m @@ -0,0 +1,32 @@ +#import <Foundation/Foundation.h> + +@interface Simple : NSObject +{ +  int _value; +} +- (int) value; +- (void) setValue: (int) newValue; +@end + +@implementation Simple +- (int) value +{ +  return _value; +} + +- (void) setValue: (int) newValue +{ +  _value = newValue; +} +@end + +int main () +{ +  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +  Simple *my_simple = [[Simple alloc] init]; +  my_simple.value = 20; +  // Set a breakpoint here. +  NSLog (@"Object has value: %d.", my_simple.value);  +  [pool drain]; +  return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-class-method/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-class-method/Makefile new file mode 100644 index 000000000000..c2d07910a6e8 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-class-method/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := class.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-class-method/TestObjCClassMethod.py b/packages/Python/lldbsuite/test/lang/objc/objc-class-method/TestObjCClassMethod.py new file mode 100644 index 000000000000..2a978bc9c024 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-class-method/TestObjCClassMethod.py @@ -0,0 +1,56 @@ +"""Test calling functions in class methods.""" + +from __future__ import print_function + + + +import os, time +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class TestObjCClassMethod(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line numbers to break inside main(). +        self.main_source = "class.m" +        self.break_line = line_number(self.main_source, '// Set breakpoint here.') + +    @skipUnlessDarwin +    @expectedFailurei386 +    @add_test_categories(['pyapi']) +    #rdar://problem/9745789 "expression" can't call functions in class methods +    def test_with_python_api(self): +        """Test calling functions in class methods.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        bpt = target.BreakpointCreateByLocation(self.main_source, self.break_line) +        self.assertTrue(bpt, VALID_BREAKPOINT) + +        # Now launch the process, and do not stop at entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        self.assertTrue(process, PROCESS_IS_VALID) + +        # The stop reason of the thread should be breakpoint. +        thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, bpt) + +        # Make sure we stopped at the first breakpoint. +        self.assertTrue (len(thread_list) != 0, "No thread stopped at our breakpoint.") +        self.assertTrue (len(thread_list) == 1, "More than one thread stopped at our breakpoint.") +             +        # Now make sure we can call a function in the class method we've stopped in. +        frame = thread_list[0].GetFrameAtIndex(0) +        self.assertTrue (frame, "Got a valid frame 0 frame.") + +        cmd_value = frame.EvaluateExpression ("(int)[Foo doSomethingWithString:@\"Hello\"]") +        self.assertTrue (cmd_value.IsValid()) +        self.assertTrue (cmd_value.GetValueAsUnsigned() == 5) diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-class-method/class.m b/packages/Python/lldbsuite/test/lang/objc/objc-class-method/class.m new file mode 100644 index 000000000000..18a2c2729bea --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-class-method/class.m @@ -0,0 +1,24 @@ +#import <Foundation/Foundation.h> + +@interface Foo : NSObject ++(int) doSomethingWithString: (NSString *) string; +-(int) doSomethingInstance: (NSString *) string; +@end + +@implementation Foo ++(int) doSomethingWithString: (NSString *) string +{ +  NSLog (@"String is: %@.", string); +  return [string length]; +} + +-(int) doSomethingInstance: (NSString *)string +{ +  return [Foo doSomethingWithString:string]; +} +@end + +int main() +{ +  return 0; // Set breakpoint here. +} diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-dyn-sbtype/.categories b/packages/Python/lldbsuite/test/lang/objc/objc-dyn-sbtype/.categories new file mode 100644 index 000000000000..9526bab96fbb --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-dyn-sbtype/.categories @@ -0,0 +1 @@ +dyntype diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-dyn-sbtype/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-dyn-sbtype/Makefile new file mode 100644 index 000000000000..dd909afba21b --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-dyn-sbtype/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m + +include $(LEVEL)/Makefile.rules + +LD_EXTRAS = -framework Foundation diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-dyn-sbtype/TestObjCDynamicSBType.py b/packages/Python/lldbsuite/test/lang/objc/objc-dyn-sbtype/TestObjCDynamicSBType.py new file mode 100644 index 000000000000..b9e84541e2df --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-dyn-sbtype/TestObjCDynamicSBType.py @@ -0,0 +1,62 @@ +""" +Test that we are able to properly report a usable dynamic type +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +@skipUnlessDarwin +class ObjCDynamicSBTypeTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # We'll use the test method name as the exe_name. +        self.exe_name = self.testMethodName +        # Find the line number to break inside main(). +        self.main_source = "main.m" +        self.line = line_number(self.main_source, '// Set breakpoint here.') + +    @skipIfi386 +    def test_dyn(self): +        """Test that we are able to properly report a usable dynamic type.""" +        d = {'EXE': self.exe_name} +        self.build(dictionary=d) +        self.setTearDownCleanup(dictionary=d) + +        exe = os.path.join(os.getcwd(), self.exe_name) +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        lldbutil.run_break_set_by_file_and_line (self, self.main_source, self.line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) + +        v_object = self.frame().FindVariable("object").GetDynamicValue(lldb.eDynamicCanRunTarget) +        v_base = self.frame().FindVariable("base").GetDynamicValue(lldb.eDynamicCanRunTarget) +        self.assertTrue(v_object.GetTypeName() == "MyDerivedClass *", "The NSObject is properly type-named") +        self.assertTrue(v_base.GetTypeName() == "MyDerivedClass *", "The Base is properly type-named") +        object_type = v_object.GetType() +        base_type = v_base.GetType() +        self.assertTrue(object_type.GetName() == "MyDerivedClass *", "The dynamic SBType for NSObject is for the correct type") +        self.assertTrue(base_type.GetName() == "MyDerivedClass *", "The dynamic SBType for Base is for the correct type") +        object_pointee_type = object_type.GetPointeeType() +        base_pointee_type = base_type.GetPointeeType() +        self.assertTrue(object_pointee_type.GetName() == "MyDerivedClass", "The dynamic type for NSObject figures out its pointee type just fine") +        self.assertTrue(base_pointee_type.GetName() == "MyDerivedClass", "The dynamic type for Base figures out its pointee type just fine") + +        self.assertTrue(object_pointee_type.GetDirectBaseClassAtIndex(0).GetName() == "MyBaseClass", "The dynamic type for NSObject can go back to its base class") +        self.assertTrue(base_pointee_type.GetDirectBaseClassAtIndex(0).GetName() == "MyBaseClass", "The dynamic type for Base can go back to its base class") + +        self.assertTrue(object_pointee_type.GetDirectBaseClassAtIndex(0).GetType().GetDirectBaseClassAtIndex(0).GetName() == "NSObject", "The dynamic type for NSObject can go up the hierarchy") +        self.assertTrue(base_pointee_type.GetDirectBaseClassAtIndex(0).GetType().GetDirectBaseClassAtIndex(0).GetName() == "NSObject", "The dynamic type for Base can go up the hierarchy") + +        self.assertTrue(object_pointee_type.GetNumberOfFields() == 2, "The dynamic type for NSObject has 2 fields") +        self.assertTrue(base_pointee_type.GetNumberOfFields() == 2, "The dynamic type for Base has 2 fields") diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-dyn-sbtype/main.m b/packages/Python/lldbsuite/test/lang/objc/objc-dyn-sbtype/main.m new file mode 100644 index 000000000000..f3587b52cd5f --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-dyn-sbtype/main.m @@ -0,0 +1,53 @@ +#import <Foundation/Foundation.h> + +@interface MyBaseClass : NSObject +{} +-(id) init; +-(int) getInt; +@end + +@implementation MyBaseClass +- (id) init { +	return (self = [super init]); +} + +- (int) getInt { +	return 1; +} +@end + +@interface MyDerivedClass : MyBaseClass +{ +	int x; +	int y; +} +-(id) init; +-(int) getInt; +@end + +@implementation MyDerivedClass +- (id) init { +	self = [super init]; +	if (self) { +		self-> x = 0; +		self->y = 1; +	} +	return self; +} + +- (int) getInt { +	y = x++; +	return x; +} +@end + + +int main (int argc, char const *argv[]) +{ +    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];	 +	NSObject* object = [[MyDerivedClass alloc] init]; +	MyBaseClass* base = [[MyDerivedClass alloc] init]; +    [pool release]; // Set breakpoint here. +    return 0; +} + diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/Makefile new file mode 100644 index 000000000000..a981f4b9035e --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := dynamic-value.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py b/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py new file mode 100644 index 000000000000..acddfb8bd647 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py @@ -0,0 +1,177 @@ +""" +Use lldb Python API to test dynamic values in ObjC +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class ObjCDynamicValueTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp().                                                                                                            +        TestBase.setUp(self) + +        # Find the line number to break for main.c.                                                                                        + +        self.source_name = 'dynamic-value.m' +        self.set_property_line = line_number(self.source_name, '// This is the line in setProperty, make sure we step to here.') +        self.handle_SourceBase = line_number(self.source_name, +                                                 '// Break here to check dynamic values.') +        self.main_before_setProperty_line = line_number(self.source_name, +                                                       '// Break here to see if we can step into real method.') + +    @skipUnlessDarwin +    @add_test_categories(['pyapi']) +    @expectedFailureDarwin("llvm.org/pr20271 rdar://18684107") +    def test_get_objc_dynamic_vals(self): +        """Test fetching ObjC dynamic values.""" +        if self.getArchitecture() == 'i386': +            # rdar://problem/9946499 +            self.skipTest("Dynamic types for ObjC V1 runtime not implemented") + +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        # Create a target from the debugger. + +        target = self.dbg.CreateTarget (exe) +        self.assertTrue(target, VALID_TARGET) + +        # Set up our breakpoints: + +        handle_SourceBase_bkpt = target.BreakpointCreateByLocation(self.source_name, self.handle_SourceBase) +        self.assertTrue(handle_SourceBase_bkpt and +                        handle_SourceBase_bkpt.GetNumLocations() == 1, +                        VALID_BREAKPOINT) + +        main_before_setProperty_bkpt = target.BreakpointCreateByLocation(self.source_name, self.main_before_setProperty_line) +        self.assertTrue(main_before_setProperty_bkpt and +                        main_before_setProperty_bkpt.GetNumLocations() == 1, +                        VALID_BREAKPOINT) + +        # Now launch the process, and do not stop at the entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        self.assertTrue(process.GetState() == lldb.eStateStopped, +                        PROCESS_STOPPED) + +        threads = lldbutil.get_threads_stopped_at_breakpoint (process, main_before_setProperty_bkpt) +        self.assertTrue (len(threads) == 1) +        thread = threads[0] + +        # +        #  At this point, myObserver has a Source pointer that is actually a KVO swizzled SourceDerived +        #  make sure we can get that properly: + +        frame = thread.GetFrameAtIndex(0) +        myObserver = frame.FindVariable('myObserver', lldb.eDynamicCanRunTarget) +        self.assertTrue (myObserver) +        myObserver_source = myObserver.GetChildMemberWithName ('_source', lldb.eDynamicCanRunTarget) +        self.examine_SourceDerived_ptr (myObserver_source) + +        # +        #  Make sure a static value can be correctly turned into a dynamic value. + +        frame = thread.GetFrameAtIndex(0) +        myObserver_static = frame.FindVariable('myObserver', lldb.eNoDynamicValues) +        self.assertTrue (myObserver_static) +        myObserver = myObserver_static.GetDynamicValue (lldb.eDynamicCanRunTarget) +        myObserver_source = myObserver.GetChildMemberWithName ('_source', lldb.eDynamicCanRunTarget) +        self.examine_SourceDerived_ptr (myObserver_source) + +        # The "frame var" code uses another path to get into children, so let's +        # make sure that works as well: + +        result = lldb.SBCommandReturnObject() + +        self.expect('frame var -d run-target myObserver->_source', 'frame var finds its way into a child member', +            patterns = ['\(SourceDerived \*\)']) +         +        # check that our ObjC GetISA() does a good job at hiding KVO swizzled classes +         +        self.expect('frame var -d run-target myObserver->_source -T', 'the KVO-ed class is hidden', +                    substrs = ['SourceDerived']) + +        self.expect('frame var -d run-target myObserver->_source -T', 'the KVO-ed class is hidden', matching = False, +                    substrs = ['NSKVONotify']) + +        # This test is not entirely related to the main thrust of this test case, but since we're here, +        # try stepping into setProperty, and make sure we get into the version in Source: + +        thread.StepInto() + +        threads = lldbutil.get_stopped_threads (process, lldb.eStopReasonPlanComplete) +        self.assertTrue (len(threads) == 1) +        line_entry = threads[0].GetFrameAtIndex(0).GetLineEntry() + +        self.assertEqual (line_entry.GetLine(), self.set_property_line) +        self.assertEqual (line_entry.GetFileSpec().GetFilename(), self.source_name)  + +        # Okay, back to the main business.  Continue to the handle_SourceBase and make sure we get the correct dynamic value. + +        threads = lldbutil.continue_to_breakpoint (process, handle_SourceBase_bkpt) +        self.assertTrue (len(threads) == 1) +        thread = threads[0] + +        frame = thread.GetFrameAtIndex(0) + +        # Get "object" using FindVariable: + +        noDynamic = lldb.eNoDynamicValues +        useDynamic = lldb.eDynamicCanRunTarget + +        object_static = frame.FindVariable ('object', noDynamic) +        object_dynamic = frame.FindVariable ('object', useDynamic) + +        # Delete this object to make sure that this doesn't cause havoc with the dynamic object that depends on it. +        del (object_static) + +        self.examine_SourceDerived_ptr (object_dynamic) +         +        # Get "this" using FindValue, make sure that works too: +        object_static = frame.FindValue ('object', lldb.eValueTypeVariableArgument, noDynamic) +        object_dynamic = frame.FindValue ('object', lldb.eValueTypeVariableArgument, useDynamic) +        del (object_static) +        self.examine_SourceDerived_ptr (object_dynamic) + +        # Get "this" using the EvaluateExpression: +        object_static = frame.EvaluateExpression ('object', noDynamic) +        object_dynamic = frame.EvaluateExpression ('object', useDynamic) +        del (object_static) +        self.examine_SourceDerived_ptr (object_dynamic) +         +        # Continue again to the handle_SourceBase and make sure we get the correct dynamic value. +        # This one looks exactly the same, but in fact this is an "un-KVO'ed" version of SourceBase, so +        # its isa pointer points to SourceBase not NSKVOSourceBase or whatever... + +        threads = lldbutil.continue_to_breakpoint (process, handle_SourceBase_bkpt) +        self.assertTrue (len(threads) == 1) +        thread = threads[0] + +        frame = thread.GetFrameAtIndex(0) + +        # Get "object" using FindVariable: + +        object_static = frame.FindVariable ('object', noDynamic) +        object_dynamic = frame.FindVariable ('object', useDynamic) + +        # Delete this object to make sure that this doesn't cause havoc with the dynamic object that depends on it. +        del (object_static) + +        self.examine_SourceDerived_ptr (object_dynamic) + +    def examine_SourceDerived_ptr (self, object): +        self.assertTrue (object) +        self.assertTrue (object.GetTypeName().find ('SourceDerived') != -1) +        derivedValue = object.GetChildMemberWithName ('_derivedValue') +        self.assertTrue (derivedValue) +        self.assertTrue (int (derivedValue.GetValue(), 0) == 30) diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/dynamic-value.m b/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/dynamic-value.m new file mode 100644 index 000000000000..2bcb76b1d9dc --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/dynamic-value.m @@ -0,0 +1,147 @@ +#import <Foundation/Foundation.h> + +// SourceBase will be the base class of Source.  We'll pass a Source object into a +// function as a SourceBase, and then see if the dynamic typing can get us through the KVO +// goo and all the way back to Source. + +@interface SourceBase: NSObject +{ +    uint32_t _value; +} +- (SourceBase *) init; +- (uint32_t) getValue; +@end + +@implementation SourceBase +- (SourceBase *) init +{ +    [super init]; +    _value = 10; +    return self; +} +- (uint32_t) getValue +{ +    return _value; +} +@end + +// Source is a class that will be observed by the Observer class below. +// When Observer sets itself up to observe this property (in initWithASource) +// the KVO system will overwrite the "isa" pointer of the object with the "kvo'ed"  +// one. + +@interface Source : SourceBase +{ +    int _property; +} +- (Source *) init; +- (void) setProperty: (int) newValue; +@end + +@implementation Source +- (Source *) init +{ +    [super init]; +    _property = 20; +    return self; +} +- (void) setProperty: (int) newValue +{ +    _property = newValue;  // This is the line in setProperty, make sure we step to here. +} +@end + +@interface SourceDerived : Source +{ +    int _derivedValue; +} +- (SourceDerived *) init; +- (uint32_t) getValue; +@end + +@implementation SourceDerived +- (SourceDerived *) init +{ +    [super init]; +    _derivedValue = 30; +    return self; +} +- (uint32_t) getValue +{ +    return _derivedValue; +} +@end + +// Observer is the object that will watch Source and cause KVO to swizzle it... + +@interface Observer : NSObject +{ +    Source *_source; +} ++ (Observer *) observerWithSource: (Source *) source; +- (Observer *) initWithASource: (Source *) source; +- (void) observeValueForKeyPath: (NSString *) path  +		       ofObject: (id) object +			 change: (NSDictionary *) change +			context: (void *) context; +@end + +@implementation Observer + ++ (Observer *) observerWithSource: (Source *) inSource; +{ +    Observer *retval; + +    retval = [[Observer alloc] initWithASource: inSource]; +    return retval; +} + +- (Observer *) initWithASource: (Source *) source +{ +    [super init]; +    _source = source; +    [_source addObserver: self  +	    forKeyPath: @"property"  +	    options: (NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) +	    context: NULL]; +    return self; +} + +- (void) observeValueForKeyPath: (NSString *) path  +		       ofObject: (id) object +			 change: (NSDictionary *) change +			context: (void *) context +{ +    printf ("Observer function called.\n"); +    return; +} +@end + +uint32_t  +handle_SourceBase (SourceBase *object) +{ +    return [object getValue];  // Break here to check dynamic values. +} + +int main () +{ +    Source *mySource; +    Observer *myObserver; + +    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + +    mySource = [[SourceDerived alloc] init]; +    myObserver = [Observer observerWithSource: mySource]; + +    [mySource setProperty: 5];      // Break here to see if we can step into real method. +     +    uint32_t return_value = handle_SourceBase (mySource); + +    SourceDerived *unwatchedSource = [[SourceDerived alloc] init]; +     +    return_value = handle_SourceBase (unwatchedSource); +     +    [pool release]; +    return 0; + +} diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/Makefile new file mode 100644 index 000000000000..fdd3b5ebfa9e --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := objc-ivar-offsets.m main.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/TestObjCIvarOffsets.py b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/TestObjCIvarOffsets.py new file mode 100644 index 000000000000..6be1d379c8eb --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/TestObjCIvarOffsets.py @@ -0,0 +1,74 @@ +"""Test printing ObjC objects that use unbacked properties - so that the static ivar offsets are incorrect.""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class TestObjCIvarOffsets(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line numbers to break inside main(). +        self.main_source = "main.m" +        self.stop_line = line_number(self.main_source, '// Set breakpoint here.') + +    @skipUnlessDarwin +    @add_test_categories(['pyapi']) +    def test_with_python_api(self): +        """Test printing ObjC objects that use unbacked properties""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        breakpoint = target.BreakpointCreateByLocation(self.main_source, self.stop_line) +        self.assertTrue(breakpoint, VALID_BREAKPOINT) + +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) +        self.assertTrue (process, "Created a process.") +        self.assertTrue (process.GetState() == lldb.eStateStopped, "Stopped it too.") + +        thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint) +        self.assertTrue (len(thread_list) == 1) +        thread = thread_list[0] +         +        frame = thread.GetFrameAtIndex(0) +        self.assertTrue (frame, "frame 0 is valid") +         +        mine = thread.GetFrameAtIndex(0).FindVariable("mine") +        self.assertTrue(mine, "Found local variable mine.") +         +        # Test the value object value for BaseClass->_backed_int + +        error = lldb.SBError() + +        mine_backed_int = mine.GetChildMemberWithName ("_backed_int") +        self.assertTrue(mine_backed_int, "Found mine->backed_int local variable.") +        backed_value = mine_backed_int.GetValueAsSigned (error) +        self.assertTrue (error.Success()) +        self.assertTrue (backed_value == 1111) +         +        # Test the value object value for DerivedClass->_derived_backed_int + +        mine_derived_backed_int = mine.GetChildMemberWithName ("_derived_backed_int") +        self.assertTrue(mine_derived_backed_int, "Found mine->derived_backed_int local variable.") +        derived_backed_value = mine_derived_backed_int.GetValueAsSigned (error) +        self.assertTrue (error.Success()) +        self.assertTrue (derived_backed_value == 3333) + +        # Make sure we also get bit-field offsets correct: + +        mine_flag2 = mine.GetChildMemberWithName ("flag2") +        self.assertTrue(mine_flag2, "Found mine->flag2 local variable.") +        flag2_value = mine_flag2.GetValueAsUnsigned (error) +        self.assertTrue (error.Success()) +        self.assertTrue (flag2_value == 7) diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/main.m b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/main.m new file mode 100644 index 000000000000..41943f48aef5 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/main.m @@ -0,0 +1,15 @@ +#include "objc-ivar-offsets.h" + +int +main () +{ +  DerivedClass *mine = [[DerivedClass alloc] init]; +  mine.backed_int = 1111; +  mine.unbacked_int = 2222; +  mine.derived_backed_int = 3333; +  mine.derived_unbacked_int = 4444; +  mine->flag1 = 1; +  mine->flag2 = 7; + +  return 0;  // Set breakpoint here. +} diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/objc-ivar-offsets.h b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/objc-ivar-offsets.h new file mode 100644 index 000000000000..99bbd427b064 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/objc-ivar-offsets.h @@ -0,0 +1,27 @@ +#import <Foundation/Foundation.h> + +@interface BaseClass : NSObject +{ +  int _backed_int; +#if !__OBJC2__ +  int _unbacked_int; +#endif +} +@property int backed_int; +@property int unbacked_int; +@end + +@interface DerivedClass : BaseClass +{ +  int _derived_backed_int; +#if !__OBJC2__ +  int _derived_unbacked_int; +#endif +  @public +  uint32_t flag1 : 1; +  uint32_t flag2 : 3; +} + +@property int derived_backed_int; +@property int derived_unbacked_int; +@end diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/objc-ivar-offsets.m b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/objc-ivar-offsets.m new file mode 100644 index 000000000000..db87adea3d13 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/objc-ivar-offsets.m @@ -0,0 +1,19 @@ +#import "objc-ivar-offsets.h" + +@implementation BaseClass +@synthesize backed_int = _backed_int; +#if __OBJC2__ +@synthesize unbacked_int; +#else +@synthesize unbacked_int = _unbacked_int; +#endif +@end + +@implementation DerivedClass +@synthesize derived_backed_int = _derived_backed_int; +#if __OBJC2__ +@synthesize derived_unbacked_int; +#else +@synthesize derived_unbacked_int = _derived_unbacked_int; +#endif +@end diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-ivar-protocols/TestIvarProtocols.py b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-protocols/TestIvarProtocols.py new file mode 100644 index 000000000000..80305e303d03 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-protocols/TestIvarProtocols.py @@ -0,0 +1,4 @@ +import lldbsuite.test.lldbinline as lldbinline +import lldbsuite.test.lldbtest as lldbtest + +lldbinline.MakeInlineTest(__file__, globals(), [lldbtest.skipIfFreeBSD,lldbtest.skipIfLinux,lldbtest.skipIfWindows]) diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-ivar-protocols/main.m b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-protocols/main.m new file mode 100644 index 000000000000..aa6c4715c33b --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-protocols/main.m @@ -0,0 +1,33 @@ +#import <Foundation/Foundation.h> + +@protocol MyProtocol +-(void)aMethod; +@end + +@interface MyClass : NSObject { +  id <MyProtocol> myId; +  NSObject <MyProtocol> *myObject; +}; + +-(void)doSomething; + +@end + +@implementation MyClass + +-(void)doSomething +{ +  NSLog(@"Hello"); //% self.expect("expression -- myId", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["id"]); +                   //% self.expect("expression -- myObject", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["NSObject"]); +} + +@end + +int main () +{ +  @autoreleasepool +  { +    MyClass *c = [MyClass alloc]; +    [c doSomething]; +  } +} diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-ivar-stripped/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-stripped/Makefile new file mode 100644 index 000000000000..4365ed9ae936 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-stripped/Makefile @@ -0,0 +1,15 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +default:        a.out.stripped + +a.out.stripped: a.out.dSYM +	strip -o a.out.stripped a.out + +clean:: +	rm -f a.out.stripped +	rm -rf a.out.stripped.dSYM + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-ivar-stripped/TestObjCIvarStripped.py b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-stripped/TestObjCIvarStripped.py new file mode 100644 index 000000000000..78c7123eefca --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-stripped/TestObjCIvarStripped.py @@ -0,0 +1,59 @@ +"""Test printing ObjC objects that use unbacked properties - so that the static ivar offsets are incorrect.""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class TestObjCIvarStripped(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line numbers to break inside main(). +        self.main_source = "main.m" +        self.stop_line = line_number(self.main_source, '// Set breakpoint here.') + +    @skipUnlessDarwin +    @skipIfDwarf    # This test requires a stripped binary and a dSYM +    @skipIfDWO      # This test requires a stripped binary and a dSYM +    @add_test_categories(['pyapi']) +    def test_with_python_api(self): +        """Test that we can find stripped Objective-C ivars in the runtime""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out.stripped") + +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        self.dbg.HandleCommand("add-dsym a.out.dSYM") + +        breakpoint = target.BreakpointCreateByLocation(self.main_source, self.stop_line) +        self.assertTrue(breakpoint.IsValid() and breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT) + +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) +        self.assertTrue (process, "Created a process.") +        self.assertTrue (process.GetState() == lldb.eStateStopped, "Stopped it too.") + +        thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint) +        self.assertTrue (len(thread_list) == 1) +        thread = thread_list[0] +         +        frame = thread.GetFrameAtIndex(0) +        self.assertTrue (frame, "frame 0 is valid") +         +        # Test the expression for mc->_foo + +        error = lldb.SBError() + +        ivar = frame.EvaluateExpression ("(mc->_foo)") +        self.assertTrue(ivar, "Got result for mc->_foo") +        ivar_value = ivar.GetValueAsSigned (error) +        self.assertTrue (error.Success()) +        self.assertTrue (ivar_value == 3) diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-ivar-stripped/main.m b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-stripped/main.m new file mode 100644 index 000000000000..ed9c1d9ec426 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-stripped/main.m @@ -0,0 +1,33 @@ +#import <Foundation/Foundation.h> + +@interface MyClass : NSObject { +@public +  int _foo; +}; + +-(id)init; +@end + +@implementation MyClass + +-(id)init +{ +  if ([super init]) +  { +    _foo = 3; +  } + +  return self; +} + +@end + +int main () +{ +  @autoreleasepool +  { +    MyClass *mc = [[MyClass alloc] init]; + +    NSLog(@"%d", mc->_foo); // Set breakpoint here. +  } +} diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/Makefile new file mode 100644 index 000000000000..ad3cb3fadcde --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py b/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py new file mode 100644 index 000000000000..ca77de261829 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py @@ -0,0 +1,103 @@ +"""Test that the Objective-C syntax for dictionary/array literals and indexing works""" + +from __future__ import print_function + + + +import unittest2 +import os, time +import lldb +import platform +import lldbsuite.test.lldbutil as lldbutil + +from distutils.version import StrictVersion + +from lldbsuite.test.lldbtest import * + +class ObjCNewSyntaxTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line number to break inside main(). +        self.line = line_number('main.m', '// Set breakpoint 0 here.') + +    @skipUnlessDarwin +    @expectedFailureAll(oslist=['macosx'], compiler='clang', compiler_version=['<', '7.0.0']) +    @unittest2.skipIf(platform.system() != "Darwin" or StrictVersion('12.0.0') > platform.release(), "Only supported on Darwin 12.0.0+") +    def test_expr(self): +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # Break inside the foo function which takes a bar_ptr argument. +        lldbutil.run_break_set_by_file_and_line (self, "main.m", self.line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) + +        # The stop reason of the thread should be breakpoint. +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +            substrs = ['stopped', +                       'stop reason = breakpoint']) + +        # The breakpoint should have a hit count of 1. +        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, +            substrs = [' resolved, hit count = 1']) + +        self.expect("expr --object-description -- immutable_array[0]", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["foo"]) + +        self.expect("expr --object-description -- mutable_array[0]", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["foo"]) + +        self.expect("expr --object-description -- mutable_array[0] = @\"bar\"", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["bar"]) + +        self.expect("expr --object-description -- mutable_array[0]", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["bar"]) + +        self.expect("expr --object-description -- immutable_dictionary[@\"key\"]", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["value"]) + +        self.expect("expr --object-description -- mutable_dictionary[@\"key\"]", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["value"]) + +        self.expect("expr --object-description -- mutable_dictionary[@\"key\"] = @\"object\"", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["object"]) + +        self.expect("expr --object-description -- mutable_dictionary[@\"key\"]", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["object"]) + +        self.expect("expr --object-description -- @[ @\"foo\", @\"bar\" ]", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["NSArray", "foo", "bar"]) + +        self.expect("expr --object-description -- @{ @\"key\" : @\"object\" }", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["key", "object"]) + +        self.expect("expr --object-description -- @'a'", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = [str(ord('a'))]) + +        self.expect("expr --object-description -- @1", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["1"]) + +        self.expect("expr --object-description -- @1l", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["1"]) + +        self.expect("expr --object-description -- @1ul", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["1"]) + +        self.expect("expr --object-description -- @1ll", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["1"]) + +        self.expect("expr --object-description -- @1ull", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["1"]) + +        self.expect("expr -- @123.45", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["NSNumber", "123.45"]) + +        self.expect("expr --object-description -- @( 1 + 3 )", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["4"]) +        self.expect("expr -- @((char*)\"Hello world\" + 6)", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["NSString", "world"]) diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/main.m b/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/main.m new file mode 100644 index 000000000000..d77ba5b10de9 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/main.m @@ -0,0 +1,21 @@ +#import <Foundation/Foundation.h> + +int main() +{ +    @autoreleasepool +    { +        // NSArrays +        NSArray *immutable_array = @[ @"foo", @"bar" ]; +        NSMutableArray *mutable_array = [NSMutableArray arrayWithCapacity:2]; +        [mutable_array addObjectsFromArray:immutable_array]; +         +        // NSDictionaries +        NSDictionary *immutable_dictionary = @{ @"key" : @"value" }; +        NSMutableDictionary *mutable_dictionary = [NSMutableDictionary dictionaryWithCapacity:1]; +        [mutable_dictionary addEntriesFromDictionary:immutable_dictionary]; + +        NSNumber *one = @1; + +        NSLog(@"Stop here"); // Set breakpoint 0 here. +    } +} diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-optimized/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-optimized/Makefile new file mode 100644 index 000000000000..aa6a7520525e --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-optimized/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m + +CFLAGS ?= -arch $(ARCH) -g -O2 +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-optimized/TestObjcOptimized.py b/packages/Python/lldbsuite/test/lang/objc/objc-optimized/TestObjcOptimized.py new file mode 100644 index 000000000000..a4a202e3f940 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-optimized/TestObjcOptimized.py @@ -0,0 +1,63 @@ +""" +Test that objective-c expression parser continues to work for optimized build. + +http://llvm.org/viewvc/llvm-project?rev=126973&view=rev +Fixed a bug in the expression parser where the 'this' +or 'self' variable was not properly read if the compiler +optimized it into a register. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil +import re + +# rdar://problem/9087739 +# test failure: objc_optimized does not work for "-C clang -A i386" +@skipUnlessDarwin +class ObjcOptimizedTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) +    myclass = "MyClass" +    mymethod = "description" +    method_spec = "-[%s %s]" % (myclass, mymethod) + +    def test_break(self): +        """Test 'expr member' continues to work for optimized build.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        lldbutil.run_break_set_by_symbol (self, self.method_spec, num_expected_locations=1, sym_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) +        self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT, +            substrs = ["stop reason = breakpoint"], +            patterns = ["frame.*0:.*%s %s" % (self.myclass, self.mymethod)]) + +        self.expect('expression member', +            startstr = "(int) $0 = 5") + +        # <rdar://problem/12693963> +        interp = self.dbg.GetCommandInterpreter() +        result = lldb.SBCommandReturnObject() +        interp.HandleCommand('frame variable self', result) +        output = result.GetOutput() + +        desired_pointer = "0x0" + +        mo = re.search("0x[0-9a-f]+", output) + +        if mo: +            desired_pointer = mo.group(0) + +        self.expect('expression (self)', +            substrs = [("(%s *) $1 = " % self.myclass), desired_pointer]) + +        self.expect('expression self->non_member', error=True, +            substrs = ["does not have a member named 'non_member'"]) diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-optimized/main.m b/packages/Python/lldbsuite/test/lang/objc/objc-optimized/main.m new file mode 100644 index 000000000000..df88eea0f86a --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-optimized/main.m @@ -0,0 +1,44 @@ +#import <Foundation/Foundation.h> + +@interface MyClass : NSObject { +  int member; +} + +- (id)initWithMember:(int)_member; +- (NSString*)description; +@end + +@implementation MyClass + +- (id)initWithMember:(int)_member +{ +    if (self = [super init]) +    { +      member = _member; +    } +    return self; +} + +- (void)dealloc +{ +    [super dealloc]; +} + +// Set a breakpoint on '-[MyClass description]' and test expressions: expr member +- (NSString *)description +{ +    return [NSString stringWithFormat:@"%d", member]; +} +@end + +int main (int argc, char const *argv[]) +{ +    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + +    MyClass *my_object = [[MyClass alloc] initWithMember:5]; + +    NSLog(@"MyObject %@", [my_object description]); + +    [pool release]; +    return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-property/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-property/Makefile new file mode 100644 index 000000000000..a1608fe5a664 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-property/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-property/TestObjCProperty.py b/packages/Python/lldbsuite/test/lang/objc/objc-property/TestObjCProperty.py new file mode 100644 index 000000000000..c22a1f1ad532 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-property/TestObjCProperty.py @@ -0,0 +1,114 @@ +""" +Use lldb Python API to verify that expression evaluation for property references uses the correct getters and setters +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class ObjCPropertyTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp().                                                                                                            +        TestBase.setUp(self) + +        # Find the line number to break for main.c.                                                                                        +        self.source_name = 'main.m' + +    @skipUnlessDarwin +    @add_test_categories(['pyapi']) +    def test_objc_properties(self): +        """Test that expr uses the correct property getters and setters""" +        if self.getArchitecture() == 'i386': +            self.skipTest("requires modern objc runtime") + +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        # Create a target from the debugger. + +        target = self.dbg.CreateTarget (exe) +        self.assertTrue(target, VALID_TARGET) + +        # Set up our breakpoints: +         +        main_bkpt = target.BreakpointCreateBySourceRegex ("Set a breakpoint here.", lldb.SBFileSpec (self.source_name)) +        self.assertTrue(main_bkpt and +                        main_bkpt.GetNumLocations() == 1, +                        VALID_BREAKPOINT) + +        # Now launch the process, and do not stop at the entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        self.assertTrue(process.GetState() == lldb.eStateStopped, +                        PROCESS_STOPPED) + +        threads = lldbutil.get_threads_stopped_at_breakpoint (process, main_bkpt) +        self.assertTrue (len(threads) == 1) +        thread = threads[0] +        frame = thread.GetFrameAtIndex(0) + +        mine = frame.FindVariable ("mine") +        self.assertTrue (mine.IsValid()) +        access_count = mine.GetChildMemberWithName ("_access_count") +        self.assertTrue (access_count.IsValid()) +        start_access_count = access_count.GetValueAsUnsigned (123456) +        self.assertTrue (start_access_count != 123456) + +        # +        # The first set of tests test calling the getter & setter of +        # a property that actually only has a getter & setter and no +        # @property. +        # +        nonexistant_value = frame.EvaluateExpression("mine.nonexistantInt", False) +        nonexistant_error = nonexistant_value.GetError() +        self.assertTrue (nonexistant_error.Success()) +        nonexistant_int = nonexistant_value.GetValueAsUnsigned (123456) +        self.assertTrue (nonexistant_int == 6) +         +        # Calling the getter function would up the access count, so make sure that happened. +         +        new_access_count = access_count.GetValueAsUnsigned (123456) +        self.assertTrue (new_access_count - start_access_count == 1) +        start_access_count = new_access_count + +        # +        # Now call the setter, then make sure that +        nonexistant_change = frame.EvaluateExpression("mine.nonexistantInt = 10", False) +        nonexistant_error = nonexistant_change.GetError() +        self.assertTrue (nonexistant_error.Success()) + +        # Calling the setter function would up the access count, so make sure that happened. +         +        new_access_count = access_count.GetValueAsUnsigned (123456) +        self.assertTrue (new_access_count - start_access_count == 1) +        start_access_count = new_access_count + +        # +        # Now we call the getter of a property that is backed by an ivar, +        # make sure it works and that we actually update the backing ivar. +        # + +        backed_value = frame.EvaluateExpression("mine.backedInt", False) +        backed_error = backed_value.GetError() +        self.assertTrue (backed_error.Success()) +        backing_value = mine.GetChildMemberWithName ("_backedInt") +        self.assertTrue (backing_value.IsValid()) +        self.assertTrue (backed_value.GetValueAsUnsigned (12345) == backing_value.GetValueAsUnsigned(23456)) + +        unbacked_value = frame.EvaluateExpression("mine.unbackedInt", False) +        unbacked_error = unbacked_value.GetError() +        self.assertTrue (unbacked_error.Success()) + +        idWithProtocol_value = frame.EvaluateExpression("mine.idWithProtocol", False) +        idWithProtocol_error = idWithProtocol_value.GetError() +        self.assertTrue (idWithProtocol_error.Success()) +        self.assertTrue (idWithProtocol_value.GetTypeName() == "id") diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-property/main.m b/packages/Python/lldbsuite/test/lang/objc/objc-property/main.m new file mode 100644 index 000000000000..2ef142be9b00 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-property/main.m @@ -0,0 +1,100 @@ +#import <Foundation/Foundation.h> + +@protocol MyProtocol + +-(const char *)hello; + +@end + +@interface BaseClass : NSObject +{ +  int _backedInt; +  int _access_count; +} + +- (int) nonexistantInt; +- (void) setNonexistantInt: (int) in_int; + +- (int) myGetUnbackedInt; +- (void) mySetUnbackedInt: (int) in_int; + +- (int) getAccessCount; + ++(BaseClass *) baseClassWithBackedInt: (int) inInt andUnbackedInt: (int) inOtherInt; + +@property(getter=myGetUnbackedInt,setter=mySetUnbackedInt:) int unbackedInt; +@property int backedInt; +@property (nonatomic, assign) id <MyProtocol> idWithProtocol; +@end + +@implementation BaseClass +@synthesize unbackedInt; +@synthesize backedInt = _backedInt; + ++ (BaseClass *) baseClassWithBackedInt: (int) inInt andUnbackedInt: (int) inOtherInt +{ +  BaseClass *new = [[BaseClass alloc] init]; +   +  new->_backedInt = inInt; +  new->unbackedInt = inOtherInt; + +  return new; +} + +- (int) myGetUnbackedInt +{ +  // NSLog (@"Getting BaseClass::unbackedInt - %d.\n", unbackedInt); +  _access_count++; +  return unbackedInt; +} + +- (void) mySetUnbackedInt: (int) in_int +{ +  // NSLog (@"Setting BaseClass::unbackedInt from %d to %d.", unbackedInt, in_int); +  _access_count++; +  unbackedInt = in_int; +} + +- (int) nonexistantInt +{ +  // NSLog (@"Getting BaseClass::nonexistantInt - %d.\n", 5); +  _access_count++; +  return 6; +} + +- (void) setNonexistantInt: (int) in_int +{ +  // NSLog (@"Setting BaseClass::nonexistantInt from 7 to %d.", in_int); +  _access_count++; +} + +- (int) getAccessCount +{ +  return _access_count; +} +@end + +int +main () +{ +  BaseClass *mine = [BaseClass baseClassWithBackedInt: 10 andUnbackedInt: 20]; +   +  // Set a breakpoint here. +  int nonexistant = mine.nonexistantInt; + +  int backedInt = mine.backedInt; + +  int unbackedInt = mine.unbackedInt; + +  id idWithProtocol = mine.idWithProtocol; + +  NSLog (@"Results for %p: nonexistant: %d backed: %d unbacked: %d accessCount: %d.", +         mine, +         nonexistant, +         backedInt, +         unbackedInt, +         [mine getAccessCount]); +  return 0; + +} + diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-runtime-ivars/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-runtime-ivars/Makefile new file mode 100644 index 000000000000..a1608fe5a664 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-runtime-ivars/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-runtime-ivars/TestRuntimeIvars.py b/packages/Python/lldbsuite/test/lang/objc/objc-runtime-ivars/TestRuntimeIvars.py new file mode 100644 index 000000000000..80305e303d03 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-runtime-ivars/TestRuntimeIvars.py @@ -0,0 +1,4 @@ +import lldbsuite.test.lldbinline as lldbinline +import lldbsuite.test.lldbtest as lldbtest + +lldbinline.MakeInlineTest(__file__, globals(), [lldbtest.skipIfFreeBSD,lldbtest.skipIfLinux,lldbtest.skipIfWindows]) diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-runtime-ivars/main.m b/packages/Python/lldbsuite/test/lang/objc/objc-runtime-ivars/main.m new file mode 100644 index 000000000000..1f5a9b077e27 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-runtime-ivars/main.m @@ -0,0 +1,10 @@ +#import <Foundation/Foundation.h> + +int main () +{ +  @autoreleasepool +  { +    NSLog(@"Hello"); //% self.expect("expression -- *((NSConcretePointerArray*)[NSPointerArray strongObjectsPointerArray])", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["count", "capacity", "options", "mutations"]); +                     //% self.expect("expression -- ((NSConcretePointerArray*)[NSPointerArray strongObjectsPointerArray])->count", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["unsigned"]); +  } +} diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-static-method-stripped/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-static-method-stripped/Makefile new file mode 100644 index 000000000000..81e7f12dea2b --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-static-method-stripped/Makefile @@ -0,0 +1,15 @@ +LEVEL = ../../../make + +OBJC_SOURCES := static.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +default:        a.out.stripped + +a.out.stripped: a.out.dSYM +	strip -o a.out.stripped a.out + +clean:: +	rm -f a.out.stripped +	rm -rf a.out.stripped.dSYM + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-static-method-stripped/TestObjCStaticMethodStripped.py b/packages/Python/lldbsuite/test/lang/objc/objc-static-method-stripped/TestObjCStaticMethodStripped.py new file mode 100644 index 000000000000..4bcc10b8b882 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-static-method-stripped/TestObjCStaticMethodStripped.py @@ -0,0 +1,65 @@ +"""Test calling functions in static methods with a stripped binary.""" + +from __future__ import print_function + + + +import os, time +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class TestObjCStaticMethodStripped(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line numbers to break inside main(). +        self.main_source = "static.m" +        self.break_line = line_number(self.main_source, '// Set breakpoint here.') + +    @skipUnlessDarwin +    @add_test_categories(['pyapi']) +    @skipIfDwarf    # This test requires a stripped binary and a dSYM +    @skipIfDWO      # This test requires a stripped binary and a dSYM +    #<rdar://problem/12042992> +    def test_with_python_api(self): +        """Test calling functions in static methods with a stripped binary.""" +        if self.getArchitecture() == 'i386': +            self.skipTest("requires modern objc runtime") +        self.build() +        exe = os.path.join(os.getcwd(), "a.out.stripped") + +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        bpt = target.BreakpointCreateByLocation(self.main_source, self.break_line) +        self.assertTrue(bpt, VALID_BREAKPOINT) + +        # Now launch the process, and do not stop at entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        self.assertTrue(process, PROCESS_IS_VALID) + +        # The stop reason of the thread should be breakpoint. +        thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, bpt) + +        # Make sure we stopped at the first breakpoint. +        self.assertTrue (len(thread_list) != 0, "No thread stopped at our breakpoint.") +        self.assertTrue (len(thread_list) == 1, "More than one thread stopped at our breakpoint.") +             +        # Now make sure we can call a function in the static method we've stopped in. +        frame = thread_list[0].GetFrameAtIndex(0) +        self.assertTrue (frame, "Got a valid frame 0 frame.") + +        cmd_value = frame.EvaluateExpression ("(char *) sel_getName (_cmd)") +        self.assertTrue (cmd_value.IsValid()) +        sel_name = cmd_value.GetSummary() +        self.assertTrue (sel_name == "\"doSomethingWithString:\"", "Got the right value for the selector as string.") + +        cmd_value = frame.EvaluateExpression ("[Foo doSomethingElseWithString:string]") +        self.assertTrue (cmd_value.IsValid()) +        string_length = cmd_value.GetValueAsUnsigned() +        self.assertTrue (string_length == 27, "Got the right value from another class method on the same class.") diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-static-method-stripped/static.m b/packages/Python/lldbsuite/test/lang/objc/objc-static-method-stripped/static.m new file mode 100644 index 000000000000..ec7b2ef67195 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-static-method-stripped/static.m @@ -0,0 +1,29 @@ +#import <Foundation/Foundation.h> + +@interface Foo : NSObject ++(void) doSomethingWithString: (NSString *) string; +-(void) doSomethingWithNothing; +@end + +@implementation Foo ++(void) doSomethingWithString: (NSString *) string +{ +  NSLog (@"String is: %@.", string); // Set breakpoint here. +} + ++(int) doSomethingElseWithString: (NSString *) string +{ +  NSLog (@"String is still: %@.", string); +  return [string length]; +} + +-(void) doSomethingWithNothing +{ +} +@end + +int main() +{ +  [Foo doSomethingWithString: @"Some string I have in mind."]; +  return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-static-method/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-static-method/Makefile new file mode 100644 index 000000000000..a8e973f6d3b1 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-static-method/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := static.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-static-method/TestObjCStaticMethod.py b/packages/Python/lldbsuite/test/lang/objc/objc-static-method/TestObjCStaticMethod.py new file mode 100644 index 000000000000..89ef1e7b6898 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-static-method/TestObjCStaticMethod.py @@ -0,0 +1,61 @@ +"""Test calling functions in static methods.""" + +from __future__ import print_function + + + +import os, time +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class TestObjCStaticMethod(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line numbers to break inside main(). +        self.main_source = "static.m" +        self.break_line = line_number(self.main_source, '// Set breakpoint here.') + +    @skipUnlessDarwin +    @add_test_categories(['pyapi']) +    #<rdar://problem/9745789> "expression" can't call functions in class methods +    def test_with_python_api(self): +        """Test calling functions in static methods.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        bpt = target.BreakpointCreateByLocation(self.main_source, self.break_line) +        self.assertTrue(bpt, VALID_BREAKPOINT) + +        # Now launch the process, and do not stop at entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        self.assertTrue(process, PROCESS_IS_VALID) + +        # The stop reason of the thread should be breakpoint. +        thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, bpt) + +        # Make sure we stopped at the first breakpoint. +        self.assertTrue (len(thread_list) != 0, "No thread stopped at our breakpoint.") +        self.assertTrue (len(thread_list) == 1, "More than one thread stopped at our breakpoint.") +             +        # Now make sure we can call a function in the static method we've stopped in. +        frame = thread_list[0].GetFrameAtIndex(0) +        self.assertTrue (frame, "Got a valid frame 0 frame.") + +        cmd_value = frame.EvaluateExpression ("(char *) sel_getName (_cmd)") +        self.assertTrue (cmd_value.IsValid()) +        sel_name = cmd_value.GetSummary() +        self.assertTrue (sel_name == "\"doSomethingWithString:\"", "Got the right value for the selector as string.") + +        cmd_value = frame.EvaluateExpression ("[self doSomethingElseWithString:string]") +        self.assertTrue (cmd_value.IsValid()) +        string_length = cmd_value.GetValueAsUnsigned() +        self.assertTrue (string_length == 27, "Got the right value from another class method on the same class.") diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-static-method/static.m b/packages/Python/lldbsuite/test/lang/objc/objc-static-method/static.m new file mode 100644 index 000000000000..ec7b2ef67195 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-static-method/static.m @@ -0,0 +1,29 @@ +#import <Foundation/Foundation.h> + +@interface Foo : NSObject ++(void) doSomethingWithString: (NSString *) string; +-(void) doSomethingWithNothing; +@end + +@implementation Foo ++(void) doSomethingWithString: (NSString *) string +{ +  NSLog (@"String is: %@.", string); // Set breakpoint here. +} + ++(int) doSomethingElseWithString: (NSString *) string +{ +  NSLog (@"String is still: %@.", string); +  return [string length]; +} + +-(void) doSomethingWithNothing +{ +} +@end + +int main() +{ +  [Foo doSomethingWithString: @"Some string I have in mind."]; +  return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-stepping/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-stepping/Makefile new file mode 100644 index 000000000000..b097fe65fce7 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-stepping/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := stepping-tests.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-stepping/TestObjCStepping.py b/packages/Python/lldbsuite/test/lang/objc/objc-stepping/TestObjCStepping.py new file mode 100644 index 000000000000..1df416d45133 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-stepping/TestObjCStepping.py @@ -0,0 +1,172 @@ +"""Test stepping through ObjC method dispatch in various forms.""" + +from __future__ import print_function + + + +import os, time +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class TestObjCStepping(TestBase): + +    def getCategories (self): +        return ['basic_process'] + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line numbers that we will step to in main: +        self.main_source = "stepping-tests.m" +        self.source_randomMethod_line = line_number (self.main_source, '// Source randomMethod start line.') +        self.sourceBase_randomMethod_line = line_number (self.main_source, '// SourceBase randomMethod start line.') +        self.source_returnsStruct_start_line = line_number (self.main_source, '// Source returnsStruct start line.') +        self.sourceBase_returnsStruct_start_line = line_number (self.main_source, '// SourceBase returnsStruct start line.') +        self.stepped_past_nil_line = line_number (self.main_source, '// Step over nil should stop here.') + +    @skipUnlessDarwin +    @add_test_categories(['pyapi']) +    def test_with_python_api(self): +        """Test stepping through ObjC method dispatch in various forms.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        self.main_source_spec = lldb.SBFileSpec (self.main_source) + +        breakpoints_to_disable = [] + +        break1 = target.BreakpointCreateBySourceRegex ("// Set first breakpoint here.", self.main_source_spec) +        self.assertTrue(break1, VALID_BREAKPOINT) +        breakpoints_to_disable.append (break1) + +        break2 = target.BreakpointCreateBySourceRegex ("// Set second breakpoint here.", self.main_source_spec) +        self.assertTrue(break2, VALID_BREAKPOINT) +        breakpoints_to_disable.append (break2) + +        break3 = target.BreakpointCreateBySourceRegex ('// Set third breakpoint here.', self.main_source_spec) +        self.assertTrue(break3, VALID_BREAKPOINT) +        breakpoints_to_disable.append (break3) + +        break4 = target.BreakpointCreateBySourceRegex ('// Set fourth breakpoint here.', self.main_source_spec) +        self.assertTrue(break4, VALID_BREAKPOINT) +        breakpoints_to_disable.append (break4) + +        break5 = target.BreakpointCreateBySourceRegex ('// Set fifth breakpoint here.', self.main_source_spec) +        self.assertTrue(break5, VALID_BREAKPOINT) +        breakpoints_to_disable.append (break5) + +        break_returnStruct_call_super = target.BreakpointCreateBySourceRegex ('// Source returnsStruct call line.', self.main_source_spec) +        self.assertTrue(break_returnStruct_call_super, VALID_BREAKPOINT) +        breakpoints_to_disable.append (break_returnStruct_call_super) + +        break_step_nil = target.BreakpointCreateBySourceRegex ('// Set nil step breakpoint here.', self.main_source_spec) +        self.assertTrue(break_step_nil, VALID_BREAKPOINT) + +        # Now launch the process, and do not stop at entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        self.assertTrue(process, PROCESS_IS_VALID) + +        # The stop reason of the thread should be breakpoint. +        threads = lldbutil.get_threads_stopped_at_breakpoint (process, break1) +        if len(threads) != 1: +            self.fail ("Failed to stop at breakpoint 1.") + +        thread = threads[0] + +        mySource = thread.GetFrameAtIndex(0).FindVariable("mySource") +        self.assertTrue(mySource, "Found mySource local variable.") +        mySource_isa = mySource.GetChildMemberWithName ("isa") +        self.assertTrue(mySource_isa, "Found mySource->isa local variable.") +        className = mySource_isa.GetSummary () + +        if self.TraceOn(): +             print(mySource_isa) + +        # Lets delete mySource so we can check that after stepping a child variable +        # with no parent persists and is useful. +        del (mySource) + +        # Now step in, that should leave us in the Source randomMethod: +        thread.StepInto() +        line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() +        self.assertTrue (line_number == self.source_randomMethod_line, "Stepped into Source randomMethod.") + +        # Now step in again, through the super call, and that should leave us in the SourceBase randomMethod: +        thread.StepInto() +        line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() +        self.assertTrue (line_number == self.sourceBase_randomMethod_line, "Stepped through super into SourceBase randomMethod.") + +        threads = lldbutil.continue_to_breakpoint (process, break2) +        self.assertTrue (len(threads) == 1, "Continued to second breakpoint in main.") + +        # Again, step in twice gets us to a stret method and a stret super call: +        thread = threads[0] +        thread.StepInto() +        line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() +        self.assertTrue (line_number == self.source_returnsStruct_start_line, "Stepped into Source returnsStruct.") + +        threads = lldbutil.continue_to_breakpoint (process, break_returnStruct_call_super) +        self.assertTrue (len(threads) == 1, "Stepped to the call super line in Source returnsStruct.") +        thread = threads[0] + +        thread.StepInto() +        line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() +        self.assertTrue (line_number == self.sourceBase_returnsStruct_start_line, "Stepped through super into SourceBase returnsStruct.") + +        # Cool now continue to get past the call that initializes the Observer, and then do our steps in again to see that  +        # we can find our way when we're stepping through a KVO swizzled object. + +        threads = lldbutil.continue_to_breakpoint (process, break3) +        self.assertTrue (len(threads) == 1, "Continued to third breakpoint in main, our object should now be swizzled.") + +        newClassName = mySource_isa.GetSummary () + +        if self.TraceOn(): +             print(mySource_isa) + +        self.assertTrue (newClassName != className, "The isa did indeed change, swizzled!") + +        # Now step in, that should leave us in the Source randomMethod: +        thread = threads[0] +        thread.StepInto() +        line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() +        self.assertTrue (line_number == self.source_randomMethod_line, "Stepped into Source randomMethod in swizzled object.") + +        # Now step in again, through the super call, and that should leave us in the SourceBase randomMethod: +        thread.StepInto() +        line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() +        self.assertTrue (line_number == self.sourceBase_randomMethod_line, "Stepped through super into SourceBase randomMethod in swizzled object.") + +        threads = lldbutil.continue_to_breakpoint (process, break4) +        self.assertTrue (len(threads) == 1, "Continued to fourth breakpoint in main.") +        thread = threads[0] + +        # Again, step in twice gets us to a stret method and a stret super call: +        thread.StepInto() +        line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() +        self.assertTrue (line_number == self.source_returnsStruct_start_line, "Stepped into Source returnsStruct in swizzled object.") + +        threads = lldbutil.continue_to_breakpoint(process, break_returnStruct_call_super) +        self.assertTrue (len(threads) == 1, "Stepped to the call super line in Source returnsStruct - second time.") +        thread = threads[0] + +        thread.StepInto() +        line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() +        self.assertTrue (line_number == self.sourceBase_returnsStruct_start_line, "Stepped through super into SourceBase returnsStruct in swizzled object.") + +        for bkpt in breakpoints_to_disable: +            bkpt.SetEnabled(False) + +        threads = lldbutil.continue_to_breakpoint (process, break_step_nil) +        self.assertTrue (len(threads) == 1, "Continued to step nil breakpoint.") + +        thread.StepInto() +        line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() +        self.assertTrue (line_number == self.stepped_past_nil_line, "Step in over dispatch to nil stepped over.") diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-stepping/stepping-tests.m b/packages/Python/lldbsuite/test/lang/objc/objc-stepping/stepping-tests.m new file mode 100644 index 000000000000..63db536dee49 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-stepping/stepping-tests.m @@ -0,0 +1,138 @@ +#import <Foundation/Foundation.h> +#include <stdio.h> + +struct return_me +{ +  int first; +  int second; +}; + +@interface SourceBase: NSObject +{ +  struct return_me my_return; +} +- (SourceBase *) initWithFirst: (int) first andSecond: (int) second; +- (void) randomMethod; +- (struct return_me) returnsStruct; +@end + +@implementation SourceBase +- (void) randomMethod +{ +  printf ("Called in SourceBase version of randomMethod.\n"); // SourceBase randomMethod start line. +} + +- (struct return_me) returnsStruct +{ +  return my_return; // SourceBase returnsStruct start line. +} + +- (SourceBase *) initWithFirst: (int) first andSecond: (int) second +{ +  my_return.first = first; +  my_return.second = second; + +  return self; +} +@end + +@interface Source : SourceBase +{ +  int _property; +} +- (void) setProperty: (int) newValue; +- (void) randomMethod; +- (struct return_me) returnsStruct; +@end + +@implementation Source +- (void) setProperty: (int) newValue +{ +  _property = newValue; +} + +- (void) randomMethod +{ +  [super randomMethod];  // Source randomMethod start line. +    printf ("Called in Source version of random method."); +} + +- (struct return_me) returnsStruct +{ +  printf ("Called in Source version of returnsStruct.\n");  // Source returnsStruct start line. +  return [super returnsStruct];                             // Source returnsStruct call line.   +} + +@end + +@interface Observer : NSObject +{ +  Source *_source; +} ++ (Observer *) observerWithSource: (Source *) source; +- (Observer *) initWithASource: (Source *) source; +- (void) observeValueForKeyPath: (NSString *) path  +		       ofObject: (id) object +			 change: (NSDictionary *) change +			context: (void *) context; +@end + +@implementation Observer + ++ (Observer *) observerWithSource: (Source *) inSource; +{ +  Observer *retval; + +  retval = [[Observer alloc] initWithASource: inSource]; +  return retval; +} + +- (Observer *) initWithASource: (Source *) source +{ +  [super init]; +  _source = source; +  [_source addObserver: self  +	    forKeyPath: @"property"  +	    options: (NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) +	    context: NULL]; +  return self; +} + +- (void) observeValueForKeyPath: (NSString *) path  +		       ofObject: (id) object +			 change: (NSDictionary *) change +			context: (void *) context +{ +  printf ("Observer function called.\n"); +  return; +} +@end + +int main () +{ +  Source *mySource; +  Observer *myObserver; +  struct return_me ret_val; + +  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + +  mySource = [[Source alloc] init]; + +  [mySource randomMethod];               // Set first breakpoint here. +  ret_val = [mySource returnsStruct];    // Set second breakpoint here. + +  myObserver = [Observer observerWithSource: mySource];   + +  [mySource randomMethod];              // Set third breakpoint here. +  ret_val = [mySource returnsStruct];   // Set fourth breakpoint here. +  [mySource setProperty: 5];            // Set fifth breakpoint here. + +  // We also had a bug where stepping into a method dispatch to nil turned +  // into continue.  So make sure that works here: + +  mySource = nil; +  [mySource randomMethod];             // Set nil step breakpoint here. +  [pool release];                      // Step over nil should stop here. +  return 0; + +} diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-struct-argument/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-struct-argument/Makefile new file mode 100644 index 000000000000..c16802966cff --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-struct-argument/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := test.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-struct-argument/TestObjCStructArgument.py b/packages/Python/lldbsuite/test/lang/objc/objc-struct-argument/TestObjCStructArgument.py new file mode 100644 index 000000000000..36cde21c9d66 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-struct-argument/TestObjCStructArgument.py @@ -0,0 +1,57 @@ +"""Test passing structs to Objective-C methods.""" + +from __future__ import print_function + + + +import os, time +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class TestObjCStructArgument(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line numbers to break inside main(). +        self.main_source = "test.m" +        self.break_line = line_number(self.main_source, '// Set breakpoint here.') + +    @skipUnlessDarwin +    @add_test_categories(['pyapi']) +    def test_with_python_api(self): +        """Test passing structs to Objective-C methods.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        bpt = target.BreakpointCreateByLocation(self.main_source, self.break_line) +        self.assertTrue(bpt, VALID_BREAKPOINT) + +        # Now launch the process, and do not stop at entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        self.assertTrue(process, PROCESS_IS_VALID) + +        # The stop reason of the thread should be breakpoint. +        thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, bpt) + +        # Make sure we stopped at the first breakpoint. +        self.assertTrue (len(thread_list) != 0, "No thread stopped at our breakpoint.") +        self.assertTrue (len(thread_list) == 1, "More than one thread stopped at our breakpoint.") +             +        frame = thread_list[0].GetFrameAtIndex(0) +        self.assertTrue (frame, "Got a valid frame 0 frame.") + +        self.expect("p [summer sumThings:tts]", substrs = ['9']) + +        self.expect("po [NSValue valueWithRect:rect]", substrs = ['NSRect: {{0, 0}, {10, 20}}']) + +        # Now make sure we can call a method that returns a struct without crashing. +        cmd_value = frame.EvaluateExpression ("[provider getRange]") +        self.assertTrue (cmd_value.IsValid()) diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-struct-argument/test.m b/packages/Python/lldbsuite/test/lang/objc/objc-struct-argument/test.m new file mode 100644 index 000000000000..8bf0ec07b710 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-struct-argument/test.m @@ -0,0 +1,34 @@ +#import <Foundation/Foundation.h> + +struct things_to_sum { +    int a; +    int b; +    int c; +}; + +@interface ThingSummer : NSObject { +}; +-(int)sumThings:(struct things_to_sum)tts; +@end + +@implementation ThingSummer +-(int)sumThings:(struct things_to_sum)tts +{ +  return tts.a + tts.b + tts.c; +} +@end + +int main() +{ +  @autoreleasepool +  { +    ThingSummer *summer = [ThingSummer alloc]; +    struct things_to_sum tts = { 2, 3, 4 }; +    int ret = [summer sumThings:tts]; + +    NSRect rect = {{0, 0}, {10, 20}};     + +    // Set breakpoint here. +    return rect.origin.x; +  } +} diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-struct-return/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-struct-return/Makefile new file mode 100644 index 000000000000..c16802966cff --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-struct-return/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := test.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-struct-return/TestObjCStructReturn.py b/packages/Python/lldbsuite/test/lang/objc/objc-struct-return/TestObjCStructReturn.py new file mode 100644 index 000000000000..010de2180825 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-struct-return/TestObjCStructReturn.py @@ -0,0 +1,53 @@ +"""Test calling functions in class methods.""" + +from __future__ import print_function + + + +import os, time +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class TestObjCClassMethod(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line numbers to break inside main(). +        self.main_source = "test.m" +        self.break_line = line_number(self.main_source, '// Set breakpoint here.') + +    @skipUnlessDarwin +    @add_test_categories(['pyapi']) +    def test_with_python_api(self): +        """Test calling functions in class methods.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        bpt = target.BreakpointCreateByLocation(self.main_source, self.break_line) +        self.assertTrue(bpt, VALID_BREAKPOINT) + +        # Now launch the process, and do not stop at entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        self.assertTrue(process, PROCESS_IS_VALID) + +        # The stop reason of the thread should be breakpoint. +        thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, bpt) + +        # Make sure we stopped at the first breakpoint. +        self.assertTrue (len(thread_list) != 0, "No thread stopped at our breakpoint.") +        self.assertTrue (len(thread_list) == 1, "More than one thread stopped at our breakpoint.") +             +        frame = thread_list[0].GetFrameAtIndex(0) +        self.assertTrue (frame, "Got a valid frame 0 frame.") + +        # Now make sure we can call a method that returns a struct without crashing. +        cmd_value = frame.EvaluateExpression ("[provider getRange]") +        self.assertTrue (cmd_value.IsValid()) diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-struct-return/test.m b/packages/Python/lldbsuite/test/lang/objc/objc-struct-return/test.m new file mode 100644 index 000000000000..aafe231ea817 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-struct-return/test.m @@ -0,0 +1,23 @@ +#import <Foundation/Foundation.h> + +@interface RangeProvider : NSObject { +}; +-(NSRange)getRange; +@end + +@implementation RangeProvider +-(NSRange)getRange +{ +  return NSMakeRange(0, 3); +} +@end + +int main() +{ +  @autoreleasepool +  { +    RangeProvider *provider = [RangeProvider alloc]; +    NSRange range = [provider getRange]; // Set breakpoint here. +    return 0; +  } +} diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-super/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-super/Makefile new file mode 100644 index 000000000000..c2d07910a6e8 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-super/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := class.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-super/TestObjCSuper.py b/packages/Python/lldbsuite/test/lang/objc/objc-super/TestObjCSuper.py new file mode 100644 index 000000000000..84d147f632da --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-super/TestObjCSuper.py @@ -0,0 +1,59 @@ +"""Test calling methods on super.""" + +from __future__ import print_function + + + +import os, time +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class TestObjCSuperMethod(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # Find the line numbers to break inside main(). +        self.main_source = "class.m" +        self.break_line = line_number(self.main_source, '// Set breakpoint here.') + +    @skipUnlessDarwin +    @expectedFailurei386 +    @add_test_categories(['pyapi']) +    def test_with_python_api(self): +        """Test calling methods on super.""" +        self.build() +        exe = os.path.join(os.getcwd(), "a.out") + +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        bpt = target.BreakpointCreateByLocation(self.main_source, self.break_line) +        self.assertTrue(bpt, VALID_BREAKPOINT) + +        # Now launch the process, and do not stop at entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        self.assertTrue(process, PROCESS_IS_VALID) + +        # The stop reason of the thread should be breakpoint. +        thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, bpt) + +        # Make sure we stopped at the first breakpoint. +        self.assertTrue (len(thread_list) != 0, "No thread stopped at our breakpoint.") +        self.assertTrue (len(thread_list) == 1, "More than one thread stopped at our breakpoint.") +             +        # Now make sure we can call a function in the class method we've stopped in. +        frame = thread_list[0].GetFrameAtIndex(0) +        self.assertTrue (frame, "Got a valid frame 0 frame.") + +        cmd_value = frame.EvaluateExpression ("[self get]") +        self.assertTrue (cmd_value.IsValid()) +        self.assertTrue (cmd_value.GetValueAsUnsigned() == 2) + +        cmd_value = frame.EvaluateExpression ("[super get]") +        self.assertTrue (cmd_value.IsValid()) +        self.assertTrue (cmd_value.GetValueAsUnsigned() == 1) diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-super/class.m b/packages/Python/lldbsuite/test/lang/objc/objc-super/class.m new file mode 100644 index 000000000000..b55b649aaaec --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/objc-super/class.m @@ -0,0 +1,39 @@ +#import <Foundation/Foundation.h> + +@interface Foo : NSObject { +} +-(int)get; +@end + +@implementation Foo +-(int)get +{ +  return 1; +} +@end + +@interface Bar : Foo { +} +-(int)get; +@end + +@implementation Bar +-(int)get +{ +  return 2;  +} + +-(int)callme +{ +  return [self get]; // Set breakpoint here. +} +@end + +int main() +{ +  @autoreleasepool +  { +    Bar *bar = [Bar alloc]; +    return [bar callme]; +  } +} diff --git a/packages/Python/lldbsuite/test/lang/objc/print-obj/Makefile b/packages/Python/lldbsuite/test/lang/objc/print-obj/Makefile new file mode 100644 index 000000000000..dba1065cd714 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/print-obj/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := blocked.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/print-obj/TestPrintObj.py b/packages/Python/lldbsuite/test/lang/objc/print-obj/TestPrintObj.py new file mode 100644 index 000000000000..5c52cc0e0697 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/print-obj/TestPrintObj.py @@ -0,0 +1,87 @@ +""" +Test "print object" where another thread blocks the print object from making progress. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * + +@skipUnlessDarwin +class PrintObjTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # My source program. +        self.source = "blocked.m" +        # Find the line numbers to break at. +        self.line = line_number(self.source, '// Set a breakpoint here.') + +    def test_print_obj(self): +        """ +        Test "print object" where another thread blocks the print object from making progress. + +        Set a breakpoint on the line in my_pthread_routine.  Then switch threads +        to the main thread, and do print the lock_me object.  Since that will +        try to get the lock already gotten by my_pthread_routime thread, it will +        have to switch to running all threads, and that should then succeed. +        """ +        d = {'EXE': 'b.out'} +        self.build(dictionary=d) +        self.setTearDownCleanup(dictionary=d) +        exe = os.path.join(os.getcwd(), 'b.out') + +        target = self.dbg.CreateTarget(exe) +        self.assertTrue(target, VALID_TARGET) + +        breakpoint = target.BreakpointCreateByLocation(self.source, self.line) +        self.assertTrue(breakpoint, VALID_BREAKPOINT) +        self.runCmd("breakpoint list") + +        # Launch the process, and do not stop at the entry point. +        process = target.LaunchSimple (None, None, self.get_process_working_directory()) + +        self.runCmd("thread backtrace all") + +        # Let's get the current stopped thread.  We'd like to switch to the +        # other thread to issue our 'po lock_me' command. +        import lldbsuite.test.lldbutil as lldbutil +        this_thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) +        self.assertTrue(this_thread) + +        # Find the other thread.  The iteration protocol of SBProcess and the +        # rich comparison methods (__eq__/__ne__) of SBThread come in handy. +        other_thread = None +        for t in process: +            if t != this_thread: +                other_thread = t +                break + +        # Set the other thread as the selected thread to issue our 'po' command.other +        self.assertTrue(other_thread) +        process.SetSelectedThread(other_thread) +        if self.TraceOn(): +            print("selected thread:" + lldbutil.get_description(other_thread)) +        self.runCmd("thread backtrace") + +        # We want to traverse the frame to the one corresponding to blocked.m to +        # issue our 'po lock_me' command. + +        depth = other_thread.GetNumFrames() +        for i in range(depth): +            frame = other_thread.GetFrameAtIndex(i) +            name = frame.GetFunctionName() +            if name == 'main': +                other_thread.SetSelectedFrame(i) +                if self.TraceOn(): +                    print("selected frame:" + lldbutil.get_description(frame)) +                break + +        self.expect("po lock_me", OBJECT_PRINTED_CORRECTLY, +            substrs = ['I am pretty special.']) diff --git a/packages/Python/lldbsuite/test/lang/objc/print-obj/blocked.m b/packages/Python/lldbsuite/test/lang/objc/print-obj/blocked.m new file mode 100644 index 000000000000..ba2497554444 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/print-obj/blocked.m @@ -0,0 +1,73 @@ +//===-- blocked.m --------------------------------------------------*- ObjC -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// This file is for testing running "print object" in a case where another thread +// blocks the print object from making progress.  Set a breakpoint on the line in  +// my_pthread_routine as indicated.  Then switch threads to the main thread, and +// do print the lock_me object.  Since that will try to get the lock already gotten +// by my_pthread_routime thread, it will have to switch to running all threads, and +// that should then succeed. +// + +#include <Foundation/Foundation.h> +#include <pthread.h> + +static pthread_mutex_t test_mutex; + +static void Mutex_Init (void) +{ +    pthread_mutexattr_t tmp_mutex_attr; +    pthread_mutexattr_init(&tmp_mutex_attr); +    pthread_mutex_init(&test_mutex, &tmp_mutex_attr); +} + +@interface LockMe :NSObject +{ +   +} +- (NSString *) description; +@end + +@implementation LockMe  +- (NSString *) description +{ +    printf ("LockMe trying to get the lock.\n"); +    pthread_mutex_lock(&test_mutex); +    printf ("LockMe got the lock.\n"); +    pthread_mutex_unlock(&test_mutex); +    return @"I am pretty special.\n"; +} +@end + +void * +my_pthread_routine (void *data) +{ +    printf ("my_pthread_routine about to enter.\n");   +    pthread_mutex_lock(&test_mutex); +    printf ("Releasing Lock.\n"); // Set a breakpoint here. +    pthread_mutex_unlock(&test_mutex); +    return NULL; +} + +int +main () +{ +  pthread_attr_t tmp_attr; +  pthread_attr_init (&tmp_attr); +  pthread_t my_pthread; + +  Mutex_Init (); + +  LockMe *lock_me = [[LockMe alloc] init]; +  pthread_create (&my_pthread, &tmp_attr, my_pthread_routine, NULL); + +  pthread_join (my_pthread, NULL); + +  return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/objc/radar-9691614/Makefile b/packages/Python/lldbsuite/test/lang/objc/radar-9691614/Makefile new file mode 100644 index 000000000000..ad3cb3fadcde --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/radar-9691614/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation diff --git a/packages/Python/lldbsuite/test/lang/objc/radar-9691614/TestObjCMethodReturningBOOL.py b/packages/Python/lldbsuite/test/lang/objc/radar-9691614/TestObjCMethodReturningBOOL.py new file mode 100644 index 000000000000..38551f671a92 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/radar-9691614/TestObjCMethodReturningBOOL.py @@ -0,0 +1,45 @@ +""" +Test that objective-c method returning BOOL works correctly. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +@skipUnlessDarwin +class MethodReturningBOOLTestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # We'll use the test method name as the exe_name. +        self.exe_name = self.testMethodName +        # Find the line number to break inside main(). +        self.main_source = "main.m" +        self.line = line_number(self.main_source, '// Set breakpoint here.') + +    def test_method_ret_BOOL(self): +        """Test that objective-c method returning BOOL works correctly.""" +        d = {'EXE': self.exe_name} +        self.build(dictionary=d) +        self.setTearDownCleanup(dictionary=d) + +        exe = os.path.join(os.getcwd(), self.exe_name) +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        lldbutil.run_break_set_by_file_and_line (self, "main.m", self.line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) +        self.expect("process status", STOPPED_DUE_TO_BREAKPOINT, +            substrs = [" at %s:%d" % (self.main_source, self.line), +                       "stop reason = breakpoint"]) + +        # rdar://problem/9691614 +        self.runCmd('p (int)[my isValid]') diff --git a/packages/Python/lldbsuite/test/lang/objc/radar-9691614/main.m b/packages/Python/lldbsuite/test/lang/objc/radar-9691614/main.m new file mode 100644 index 000000000000..bb87d673452c --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/radar-9691614/main.m @@ -0,0 +1,67 @@ +#import <Foundation/Foundation.h> +#include <stdio.h> + +@interface MyString : NSObject { +    NSString *str; +    NSDate *date; +    BOOL _is_valid; +} + +- (id)initWithNSString:(NSString *)string; +- (BOOL)isValid; +@end + +@implementation MyString +- (id)initWithNSString:(NSString *)string +{ +    if (self = [super init]) +    { +        str = [NSString stringWithString:string]; +        date = [NSDate date]; +    } +    _is_valid = YES; +    return self; +} + +- (BOOL)isValid +{ +    return _is_valid; +} + +- (void)dealloc +{ +    [date release]; +    [str release]; +    [super dealloc]; +} + +- (NSString *)description +{ +    return [str stringByAppendingFormat:@" with timestamp: %@", date]; +} +@end + +void +Test_MyString (const char *program) +{ +    NSString *str = [NSString stringWithFormat:@"Hello from '%s'", program]; +    MyString *my = [[MyString alloc] initWithNSString:str]; +    if ([my isValid]) +        printf("my is valid!\n"); + +    NSLog(@"NSString instance: %@", [str description]); // Set breakpoint here. +                                                        // Test 'p (int)[my isValid]'. +                                                        // The expression parser should not crash -- rdar://problem/9691614. + +    NSLog(@"MyString instance: %@", [my description]); +} + +int main (int argc, char const *argv[]) +{ +    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + +    Test_MyString (argv[0]); + +    [pool release]; +    return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/objc/rdar-10967107/Makefile b/packages/Python/lldbsuite/test/lang/objc/rdar-10967107/Makefile new file mode 100644 index 000000000000..ad3cb3fadcde --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/rdar-10967107/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation diff --git a/packages/Python/lldbsuite/test/lang/objc/rdar-10967107/TestRdar10967107.py b/packages/Python/lldbsuite/test/lang/objc/rdar-10967107/TestRdar10967107.py new file mode 100644 index 000000000000..0902527d424c --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/rdar-10967107/TestRdar10967107.py @@ -0,0 +1,44 @@ +""" +Test that CoreFoundation classes CFGregorianDate and CFRange are not improperly uniqued +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +@skipUnlessDarwin +class Rdar10967107TestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # We'll use the test method name as the exe_name. +        self.exe_name = self.testMethodName +        # Find the line number to break inside main(). +        self.main_source = "main.m" +        self.line = line_number(self.main_source, '// Set breakpoint here.') + +    def test_cfrange_diff_cfgregoriandate(self): +        """Test that CoreFoundation classes CFGregorianDate and CFRange are not improperly uniqued.""" +        d = {'EXE': self.exe_name} +        self.build(dictionary=d) +        self.setTearDownCleanup(dictionary=d) + +        exe = os.path.join(os.getcwd(), self.exe_name) +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        lldbutil.run_break_set_by_file_and_line (self, self.main_source, self.line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) +        # check that each type is correctly bound to its list of children +        self.expect("frame variable cf_greg_date --raw", substrs = ['year','month','day','hour','minute','second']) +        self.expect("frame variable cf_range --raw", substrs = ['location','length']) +        # check that printing both does not somehow confuse LLDB +        self.expect("frame variable  --raw", substrs = ['year','month','day','hour','minute','second','location','length']) diff --git a/packages/Python/lldbsuite/test/lang/objc/rdar-10967107/main.m b/packages/Python/lldbsuite/test/lang/objc/rdar-10967107/main.m new file mode 100644 index 000000000000..386a458950b6 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/rdar-10967107/main.m @@ -0,0 +1,13 @@ +#import <Foundation/Foundation.h> + +int main (int argc, char const *argv[]) +{ +    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + +	NSDate *date1 = [NSDate date]; +	CFGregorianDate cf_greg_date = CFAbsoluteTimeGetGregorianDate(CFDateGetAbsoluteTime((CFDateRef)date1), NULL); +	CFRange cf_range = {4,4}; + +    [pool release]; // Set breakpoint here. +    return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/objc/rdar-11355592/Makefile b/packages/Python/lldbsuite/test/lang/objc/rdar-11355592/Makefile new file mode 100644 index 000000000000..ad3cb3fadcde --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/rdar-11355592/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation diff --git a/packages/Python/lldbsuite/test/lang/objc/rdar-11355592/TestRdar11355592.py b/packages/Python/lldbsuite/test/lang/objc/rdar-11355592/TestRdar11355592.py new file mode 100644 index 000000000000..42120a57834c --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/rdar-11355592/TestRdar11355592.py @@ -0,0 +1,65 @@ +""" +Test that we do not attempt to make a dynamic type for a 'const char*' +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +@skipUnlessDarwin +class Rdar10967107TestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # We'll use the test method name as the exe_name. +        self.exe_name = self.testMethodName +        # Find the line number to break inside main(). +        self.main_source = "main.m" +        self.line = line_number(self.main_source, '// Set breakpoint here.') + +    def test_charstar_dyntype(self): +        """Test that we do not attempt to make a dynamic type for a 'const char*'""" +        d = {'EXE': self.exe_name} +        self.build(dictionary=d) +        self.setTearDownCleanup(dictionary=d) + +        exe = os.path.join(os.getcwd(), self.exe_name) +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        lldbutil.run_break_set_by_file_and_line (self, self.main_source, self.line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) +        # check that we correctly see the const char*, even with dynamic types on +        self.expect("frame variable my_string", substrs = ['const char *']) +        self.expect("frame variable my_string --dynamic-type run-target", substrs = ['const char *']) +        # check that expr also gets it right +        self.expect("expr my_string", substrs = ['const char *']) +        self.expect("expr -d run -- my_string", substrs = ['const char *']) +        # but check that we get the real Foolie as such +        self.expect("frame variable my_foolie", substrs = ['FoolMeOnce *']) +        self.expect("frame variable my_foolie --dynamic-type run-target", substrs = ['FoolMeOnce *']) +        # check that expr also gets it right +        self.expect("expr my_foolie", substrs = ['FoolMeOnce *']) +        self.expect("expr -d run -- my_foolie", substrs = ['FoolMeOnce *']) +        # now check that assigning a true string does not break anything +        self.runCmd("next") +        # check that we correctly see the const char*, even with dynamic types on +        self.expect("frame variable my_string", substrs = ['const char *']) +        self.expect("frame variable my_string --dynamic-type run-target", substrs = ['const char *']) +        # check that expr also gets it right +        self.expect("expr my_string", substrs = ['const char *']) +        self.expect("expr -d run -- my_string", substrs = ['const char *']) +        # but check that we get the real Foolie as such +        self.expect("frame variable my_foolie", substrs = ['FoolMeOnce *']) +        self.expect("frame variable my_foolie --dynamic-type run-target", substrs = ['FoolMeOnce *']) +        # check that expr also gets it right +        self.expect("expr my_foolie", substrs = ['FoolMeOnce *']) +        self.expect("expr -d run -- my_foolie", substrs = ['FoolMeOnce *']) diff --git a/packages/Python/lldbsuite/test/lang/objc/rdar-11355592/main.m b/packages/Python/lldbsuite/test/lang/objc/rdar-11355592/main.m new file mode 100644 index 000000000000..09b3b18a7878 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/rdar-11355592/main.m @@ -0,0 +1,37 @@ +#import <Foundation/Foundation.h> + +@interface FoolMeOnce : NSObject +{ +	int32_t value_one; // ivars needed to make 32-bit happy +	int32_t value_two; +} +- (FoolMeOnce *) initWithFirst: (int32_t) first andSecond: (int32_t) second; + +@property int32_t value_one; +@property int32_t value_two; + +@end + +@implementation FoolMeOnce +@synthesize value_one; +@synthesize value_two; +- (FoolMeOnce *) initWithFirst: (int32_t) first andSecond: (int32_t) second +{ +  value_one = first; +  value_two = second; +  return self; +} +@end + +int main (int argc, char const *argv[]) +{ +    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + +    FoolMeOnce *my_foolie = [[FoolMeOnce alloc] initWithFirst: 20 andSecond: 55]; +    const char *my_string = (char *) my_foolie; + +    my_string = "Now this is a REAL string..."; // Set breakpoint here. + +    [pool release]; +    return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/objc/rdar-12408181/Makefile b/packages/Python/lldbsuite/test/lang/objc/rdar-12408181/Makefile new file mode 100644 index 000000000000..385b557c9af0 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/rdar-12408181/Makefile @@ -0,0 +1,11 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m + +include $(LEVEL)/Makefile.rules + +ifneq (,$(findstring arm,$(ARCH))) +    LD_EXTRAS = -framework Foundation -framework UIKit +else +    LD_EXTRAS = -framework Foundation -framework Cocoa +endif diff --git a/packages/Python/lldbsuite/test/lang/objc/rdar-12408181/TestRdar12408181.py b/packages/Python/lldbsuite/test/lang/objc/rdar-12408181/TestRdar12408181.py new file mode 100644 index 000000000000..b95d95106032 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/rdar-12408181/TestRdar12408181.py @@ -0,0 +1,48 @@ +""" +Test that we are able to find out how many children NSWindow has +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +@skipUnlessDarwin +class Rdar12408181TestCase(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    def setUp(self): +        # Call super's setUp(). +        TestBase.setUp(self) +        # We'll use the test method name as the exe_name. +        self.exe_name = self.testMethodName +        # Find the line number to break inside main(). +        self.main_source = "main.m" +        self.line = line_number(self.main_source, '// Set breakpoint here.') + +    def test_nswindow_count(self): +        """Test that we are able to find out how many children NSWindow has.""" +        d = {'EXE': self.exe_name} +        self.build(dictionary=d) +        self.setTearDownCleanup(dictionary=d) + +        exe = os.path.join(os.getcwd(), self.exe_name) +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        lldbutil.run_break_set_by_file_and_line (self, self.main_source, self.line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) +        if self.frame().EvaluateExpression('(void*)_CGSDefaultConnection()').GetValueAsUnsigned() != 0: +            window = self.frame().FindVariable("window") +            window_dynamic = window.GetDynamicValue(lldb.eDynamicCanRunTarget) +            self.assertTrue(window.GetNumChildren() > 1, "NSWindow (static) only has 1 child!") +            self.assertTrue(window_dynamic.GetNumChildren() > 1, "NSWindow (dynamic) only has 1 child!") +            self.assertTrue(window.GetChildAtIndex(0).IsValid(), "NSWindow (static) has an invalid child") +            self.assertTrue(window_dynamic.GetChildAtIndex(0).IsValid(), "NSWindow (dynamic) has an invalid child") +        else: +            self.skipTest('no WindowServer connection') diff --git a/packages/Python/lldbsuite/test/lang/objc/rdar-12408181/main.m b/packages/Python/lldbsuite/test/lang/objc/rdar-12408181/main.m new file mode 100644 index 000000000000..858ba2a4a22f --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/rdar-12408181/main.m @@ -0,0 +1,24 @@ +#import <Foundation/Foundation.h> +#if defined (__i386__) || defined (__x86_64__) +#import <Cocoa/Cocoa.h> +#else +#import <UIKit/UIKit.h> +#endif + +int main (int argc, char const *argv[]) +{ +    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#if defined (__i386__) || defined (__x86_64__) + +    [NSApplication sharedApplication]; +    NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0,0,100,100) styleMask:NSBorderlessWindowMask backing:NSBackingStoreRetained defer:NO]; +    [window setCanHide:YES]; +#else +    [UIApplication sharedApplication]; +    CGRect rect = { 0, 0, 100, 100}; +    UIWindow* window = [[UIWindow alloc] initWithFrame:rect]; +#endif +    [pool release]; // Set breakpoint here. +    return 0; +} + diff --git a/packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.h b/packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.h new file mode 100644 index 000000000000..20a81faa1017 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.h @@ -0,0 +1,12 @@ +#import <Foundation/Foundation.h> + +@class InternalClass; + +@interface Bar : NSObject { +    @private +    InternalClass *storage; +} + +- (NSString *)description; + +@end
\ No newline at end of file diff --git a/packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.m b/packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.m new file mode 100644 index 000000000000..46d7e3888751 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.m @@ -0,0 +1,43 @@ +#import "Bar.h" + +@interface InternalClass : NSObject { +    @public +    NSString *foo; +    NSString *bar; +} +@end + +@implementation InternalClass +@end + +@interface Bar ()  +{ +    NSString *_hidden_ivar; +} + +@end + +@implementation Bar + +- (id)init +{ +    self = [super init]; +    if (self) { +        _hidden_ivar = [NSString stringWithFormat:@"%p: @Bar", self]; +    } +    return self; // Set breakpoint where Bar is an implementation +} + +- (void)dealloc +{ +    [_hidden_ivar release]; +    [super dealloc]; +} + +- (NSString *)description +{ +    return [_hidden_ivar copyWithZone:NULL]; +} + +@end + 
\ No newline at end of file diff --git a/packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.h b/packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.h new file mode 100644 index 000000000000..14ff9eed50fd --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.h @@ -0,0 +1,11 @@ +#import <Foundation/Foundation.h> + +#import "Bar.h" + +@interface Foo : NSObject { +    Bar *_bar; +} + +- (NSString *)description; + +@end
\ No newline at end of file diff --git a/packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.m b/packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.m new file mode 100644 index 000000000000..bcdeaeffc29a --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.m @@ -0,0 +1,25 @@ +#import "Foo.h" + +@implementation Foo + +- (id)init +{ +    self = [super init]; +    if (self) { +        _bar = [[Bar alloc] init]; +    } +    return self; // Set breakpoint where Bar is an interface +} + +- (void)dealloc +{ +    [_bar release]; +    [super dealloc]; +} + +- (NSString *)description +{ +    return [NSString stringWithFormat:@"%p: @Foo { _bar = %@ }", self, _bar]; +} + +@end diff --git a/packages/Python/lldbsuite/test/lang/objc/real-definition/Makefile b/packages/Python/lldbsuite/test/lang/objc/real-definition/Makefile new file mode 100644 index 000000000000..61cc3b3b6db8 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/real-definition/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := Bar.m Foo.m main.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/real-definition/TestRealDefinition.py b/packages/Python/lldbsuite/test/lang/objc/real-definition/TestRealDefinition.py new file mode 100644 index 000000000000..30fd2a5b0f6d --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/real-definition/TestRealDefinition.py @@ -0,0 +1,86 @@ +"""Test that types defined in shared libraries work correctly.""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class TestRealDefinition(TestBase): + +    mydir = TestBase.compute_mydir(__file__) + +    @skipUnlessDarwin +    def test_frame_var_after_stop_at_interface(self): +        """Test that we can find the implementation for an objective C type""" +        if self.getArchitecture() == 'i386': +            self.skipTest("requires modern objc runtime") +        self.build() +        self.common_setup() + +        line = line_number('Foo.m', '// Set breakpoint where Bar is an interface') +        lldbutil.run_break_set_by_file_and_line (self, 'Foo.m', line, num_expected_locations=1, loc_exact=True); + +        self.runCmd("run", RUN_SUCCEEDED) + +        # The stop reason of the thread should be breakpoint. +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +            substrs = ['stopped', +                       'stop reason = breakpoint']) + +        # Run and stop at Foo +        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, +            substrs = [' resolved, hit count = 1']) + +        self.runCmd("continue", RUN_SUCCEEDED) + +        # Run at stop at main +        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, +            substrs = [' resolved, hit count = 1']) +             +        # This should display correctly. +        self.expect("frame variable foo->_bar->_hidden_ivar", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["(NSString *)", "foo->_bar->_hidden_ivar = 0x"]) + +    @skipUnlessDarwin +    def test_frame_var_after_stop_at_implementation(self): +        """Test that we can find the implementation for an objective C type""" +        if self.getArchitecture() == 'i386': +            self.skipTest("requires modern objc runtime") +        self.build() +        self.common_setup() + +        line = line_number('Bar.m', '// Set breakpoint where Bar is an implementation') +        lldbutil.run_break_set_by_file_and_line (self, 'Bar.m', line, num_expected_locations=1, loc_exact=True) + +        self.runCmd("run", RUN_SUCCEEDED) + +        # The stop reason of the thread should be breakpoint. +        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +            substrs = ['stopped', +                       'stop reason = breakpoint']) + +        # Run and stop at Foo +        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, +            substrs = [' resolved, hit count = 1']) + +        self.runCmd("continue", RUN_SUCCEEDED) + +        # Run at stop at main +        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, +            substrs = [' resolved, hit count = 1']) + +        # This should display correctly. +        self.expect("frame variable foo->_bar->_hidden_ivar", VARIABLES_DISPLAYED_CORRECTLY, +            substrs = ["(NSString *)", "foo->_bar->_hidden_ivar = 0x"]) + +    def common_setup(self): +        exe = os.path.join(os.getcwd(), "a.out") +        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + +        # Break inside the foo function which takes a bar_ptr argument. +        line = line_number('main.m', '// Set breakpoint in main') +        lldbutil.run_break_set_by_file_and_line (self, "main.m", line, num_expected_locations=1, loc_exact=True) diff --git a/packages/Python/lldbsuite/test/lang/objc/real-definition/main.m b/packages/Python/lldbsuite/test/lang/objc/real-definition/main.m new file mode 100644 index 000000000000..8c31dc9abb31 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/real-definition/main.m @@ -0,0 +1,13 @@ +#include <stdio.h> +#include <stdint.h> +#import <Foundation/Foundation.h> +#import "Foo.h" + +int main (int argc, char const *argv[]) +{ +    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +    Foo *foo = [[Foo alloc] init]; +    NSLog (@"foo is %@", foo); // Set breakpoint in main +    [pool release]; +    return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/objc/sample/Makefile b/packages/Python/lldbsuite/test/lang/objc/sample/Makefile new file mode 100644 index 000000000000..a1608fe5a664 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/sample/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/sample/main.m b/packages/Python/lldbsuite/test/lang/objc/sample/main.m new file mode 100644 index 000000000000..9dffc71aaac6 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/sample/main.m @@ -0,0 +1,70 @@ +#import <Foundation/Foundation.h> + + +@interface MyString : NSObject { +    NSString *_string; +    NSDate *_date; +} +- (id)initWithNSString:(NSString *)string; + +@property (copy) NSString *string; +@property (readonly,getter=getTheDate) NSDate *date; + +- (NSDate *) getTheDate; +@end + +@implementation MyString + +@synthesize string = _string; +@synthesize date = _date; + +- (id)initWithNSString:(NSString *)string +{ +    if (self = [super init]) +    { +        _string = [NSString stringWithString:string]; +        _date = [NSDate date];             +    } +    return self; +} + +- (void) dealloc +{ +    [_date release]; +    [_string release]; +    [super dealloc]; +} + +- (NSDate *) getTheDate +{ +    return _date; +} + +- (NSString *)description +{ +    return [_string stringByAppendingFormat:@" with timestamp: %@", _date]; +} +@end + +int main (int argc, char const *argv[]) +{ +    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +    static NSString *g_global_nsstr = @"Howdy"; +     +    MyString *myStr = [[MyString alloc] initWithNSString: [NSString stringWithFormat:@"string %i", 1]]; +    NSString *str1 = myStr.string; +    NSString *str2 = [NSString stringWithFormat:@"string %i", 2]; +    NSString *str3 = [NSString stringWithFormat:@"string %i", 3]; +    NSArray *array = [NSArray arrayWithObjects: str1, str2, str3, nil]; +    NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: +                            str1, @"1",  +                            str2, @"2",  +                            str3, @"3",  +                            myStr.date, @"date", +                            nil]; + +    id str_id = str1; +    SEL sel = @selector(length); +    [pool release]; +    return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/objc/self/Makefile b/packages/Python/lldbsuite/test/lang/objc/self/Makefile new file mode 100644 index 000000000000..bdae30428be4 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/self/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m +LD_EXTRAS ?= -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/self/TestObjCSelf.py b/packages/Python/lldbsuite/test/lang/objc/self/TestObjCSelf.py new file mode 100644 index 000000000000..37db151f9ae3 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/self/TestObjCSelf.py @@ -0,0 +1,36 @@ +""" +Tests that ObjC member variables are available where they should be. +""" +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class ObjCSelfTestCase(TestBase): +     +    mydir = TestBase.compute_mydir(__file__) +     +    @skipUnlessDarwin +    def test_with_run_command(self): +        """Test that the appropriate member variables are available when stopped in Objective-C class and instance methods""" +        self.build() +        self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + +        self.set_breakpoint(line_number('main.m', '// breakpoint 1')) +        self.set_breakpoint(line_number('main.m', '// breakpoint 2')) + +        self.runCmd("process launch", RUN_SUCCEEDED) + +        self.expect("expression -- m_a = 2", +                    startstr = "(int) $0 = 2") +         +        self.runCmd("process continue") +         +        # This would be disallowed if we enforced const.  But we don't. +        self.expect("expression -- m_a = 2", +                    error=True) +         +        self.expect("expression -- s_a",  +                    startstr = "(int) $1 = 5") + +    def set_breakpoint(self, line): +        lldbutil.run_break_set_by_file_and_line (self, "main.m", line, num_expected_locations=1, loc_exact=True) diff --git a/packages/Python/lldbsuite/test/lang/objc/self/main.m b/packages/Python/lldbsuite/test/lang/objc/self/main.m new file mode 100644 index 000000000000..928aaf2ff024 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/self/main.m @@ -0,0 +1,54 @@ +//===-- main.m ------------------------------------------*- Objective-C -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +@interface A : NSObject +{ +    int m_a; +} +-(id)init; +-(void)accessMember:(int)a; ++(void)accessStaticMember:(int)a; +@end + +static int s_a = 5; + +@implementation A +-(id)init +{ +    self = [super init]; +     +    if (self) +        m_a = 2; + +    return self; +} + +-(void)accessMember:(int)a +{ +    m_a = a; // breakpoint 1 +} + ++(void)accessStaticMember:(int)a +{ +    s_a = a; // breakpoint 2 +} +@end + +int main() +{ +    NSAutoreleasePool *pool = [NSAutoreleasePool alloc]; +    A *my_a = [[A alloc] init]; +     +    [my_a accessMember:3]; +    [A accessStaticMember:5]; +     +    [pool release]; +} | 
