diff options
author | dim <dim@FreeBSD.org> | 2016-01-06 20:12:03 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2016-01-06 20:12:03 +0000 |
commit | 78b9749c0a4ea980a8b934645da6ae98fcc665e8 (patch) | |
tree | dd2a1ddf0476664c2b823409c36cbccd52662ca7 /packages/Python/lldbsuite/test/lang/objc | |
parent | 60cb593f9d55fa5ca7a5372b731f2330345b4b9a (diff) | |
download | FreeBSD-src-78b9749c0a4ea980a8b934645da6ae98fcc665e8.zip FreeBSD-src-78b9749c0a4ea980a8b934645da6ae98fcc665e8.tar.gz |
Vendor import of lldb trunk r256945:
https://llvm.org/svn/llvm-project/lldb/trunk@256945
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 0000000..72cf07c --- /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 0000000..0af8359 --- /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 0000000..6a1cde1 --- /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 0000000..1ceac33 --- /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 0000000..1098a91 --- /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 0000000..0c56f45 --- /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 0000000..85bbd06 --- /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 0000000..4d2139f --- /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 0000000..b99925b --- /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 0000000..207518a --- /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 0000000..8e5256e --- /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 0000000..ce2ccd2 --- /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 0000000..a9298dd --- /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 0000000..88db12e --- /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 0000000..8358bd5 --- /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 0000000..b61a7702 --- /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 0000000..a85f0fe --- /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 0000000..8f19172 --- /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 0000000..72952c1 --- /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 0000000..8a43abe --- /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 0000000..519bec5 --- /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 0000000..53202aa --- /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 0000000..0c316b2 --- /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 0000000..59652d4 --- /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 0000000..1a10ce0 --- /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 0000000..1768d11 --- /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 0000000..e85dd8f --- /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 0000000..1795d56 --- /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 0000000..329ceab --- /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 0000000..9ed2bb9 --- /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 0000000..da28d1e --- /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 0000000..85b2fcf --- /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 0000000..14f911f --- /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 0000000..e42b59f --- /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 0000000..2c052aa --- /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 0000000..5452ffd --- /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 0000000..cbd95de --- /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 0000000..8667e62 --- /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 0000000..8ebfb0c --- /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 0000000..2ef8064 --- /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 0000000..d03dde0 --- /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 0000000..d6a2619 --- /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 0000000..6ad9e00 --- /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 0000000..d9d94a8 --- /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 0000000..13a5bf3 --- /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 0000000..2ef8064 --- /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 0000000..ad3c85d --- /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 0000000..d50d010 --- /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 0000000..ad3cb3f --- /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 0000000..04fc072 --- /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 0000000..99b50f9 --- /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 0000000..910d494 --- /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 0000000..38ef853 --- /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 0000000..50d2f0a --- /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 0000000..7f7baeb --- /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 0000000..5d2414e --- /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 0000000..3ec78fd0 --- /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 0000000..314f1cb --- /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 0000000..f7ce280 --- /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 0000000..6dd8cbc --- /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 0000000..a1608fe --- /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 0000000..533ec2f --- /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 0000000..4a09a28 --- /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 0000000..c2d0791 --- /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 0000000..2a978bc --- /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 0000000..18a2c27 --- /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 0000000..9526bab --- /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 0000000..dd909af --- /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 0000000..b9e8454 --- /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 0000000..f3587b5 --- /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 0000000..a981f4b --- /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 0000000..acddfb8 --- /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 0000000..2bcb76b --- /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 0000000..fdd3b5e --- /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 0000000..6be1d37 --- /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 0000000..41943f4 --- /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 0000000..99bbd42 --- /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 0000000..db87ade --- /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 0000000..80305e3 --- /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 0000000..aa6c471 --- /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 0000000..4365ed9 --- /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 0000000..78c7123 --- /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 0000000..ed9c1d9 --- /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 0000000..ad3cb3f --- /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 0000000..ca77de2 --- /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 0000000..d77ba5b --- /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 0000000..aa6a752 --- /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 0000000..a4a202e --- /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 0000000..df88eea --- /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 0000000..a1608fe --- /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 0000000..c22a1f1 --- /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 0000000..2ef142b --- /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 0000000..a1608fe --- /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 0000000..80305e3 --- /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 0000000..1f5a9b0 --- /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 0000000..81e7f12 --- /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 0000000..4bcc10b --- /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 0000000..ec7b2ef --- /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 0000000..a8e973f --- /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 0000000..89ef1e7 --- /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 0000000..ec7b2ef --- /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 0000000..b097fe6 --- /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 0000000..1df416d --- /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 0000000..63db536 --- /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 0000000..c168029 --- /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 0000000..36cde21 --- /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 0000000..8bf0ec0 --- /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 0000000..c168029 --- /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 0000000..010de21 --- /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 0000000..aafe231 --- /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 0000000..c2d0791 --- /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 0000000..84d147f --- /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 0000000..b55b649 --- /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 0000000..dba1065 --- /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 0000000..5c52cc0 --- /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 0000000..ba24975 --- /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 0000000..ad3cb3f --- /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 0000000..38551f6 --- /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 0000000..bb87d67 --- /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 0000000..ad3cb3f --- /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 0000000..0902527 --- /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 0000000..386a458 --- /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 0000000..ad3cb3f --- /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 0000000..42120a5 --- /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 0000000..09b3b18 --- /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 0000000..385b557 --- /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 0000000..b95d951 --- /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 0000000..858ba2a --- /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 0000000..20a81fa --- /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 0000000..46d7e38 --- /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 0000000..14ff9ee --- /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 0000000..bcdeaef --- /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 0000000..61cc3b3 --- /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 0000000..30fd2a5 --- /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 0000000..8c31dc9 --- /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 0000000..a1608fe --- /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 0000000..9dffc71 --- /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 0000000..bdae304 --- /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 0000000..37db151 --- /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 0000000..928aaf2 --- /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]; +} |