aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEnrico Granata <egranata@apple.com>2015-06-25 19:17:04 +0000
committerEnrico Granata <egranata@apple.com>2015-06-25 19:17:04 +0000
commit2d061e20f6eb63c470fb0b5a1f1ae8f8fc6067a9 (patch)
tree1440d230452a129c75b003f15b0ef0954c6de2fd
parent1f93e86768e827bbef5991178ced4bff5eff6214 (diff)
downloadllvm-2d061e20f6eb63c470fb0b5a1f1ae8f8fc6067a9.zip
llvm-2d061e20f6eb63c470fb0b5a1f1ae8f8fc6067a9.tar.gz
llvm-2d061e20f6eb63c470fb0b5a1f1ae8f8fc6067a9.tar.bz2
Fix a bug where we were trying to reconstruct ivars of ObjC types from the runtime in "expression parser mode"
The expression parser mode allows UnknownAnyTy to make it all the way through, but that is bad for ivars because it means type layout fails horribly (as in, clang crashes) This patch fixes the issue by using the "variables view mode", which masks UnknownAnyTy as empty-type, and pointer-to UnknownAnyTy as void* This, in turn, allows LLDB to properly reconstruct ivars of IMP type in ObjC type - as per accompanying test case Fixes rdar://21471326 llvm-svn: 240677
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp2
-rw-r--r--lldb/test/lang/objc/ivar-IMP/Makefile12
-rw-r--r--lldb/test/lang/objc/ivar-IMP/TestObjCiVarIMP.py75
-rw-r--r--lldb/test/lang/objc/ivar-IMP/myclass.h6
-rw-r--r--lldb/test/lang/objc/ivar-IMP/myclass.m16
-rw-r--r--lldb/test/lang/objc/ivar-IMP/repro.m7
6 files changed, 117 insertions, 1 deletions
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
index 76ac690..2c4ecf4 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
@@ -496,7 +496,7 @@ AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl)
if (!name || !type)
return false;
- const bool for_expression = true;
+ const bool for_expression = false;
if (log)
log->Printf("[ AOTV::FD] Instance variable [%s] [%s], offset at %" PRIx64, name, type, offset_ptr);
diff --git a/lldb/test/lang/objc/ivar-IMP/Makefile b/lldb/test/lang/objc/ivar-IMP/Makefile
new file mode 100644
index 0000000..329ceab
--- /dev/null
+++ b/lldb/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/lldb/test/lang/objc/ivar-IMP/TestObjCiVarIMP.py b/lldb/test/lang/objc/ivar-IMP/TestObjCiVarIMP.py
new file mode 100644
index 0000000..d908449
--- /dev/null
+++ b/lldb/test/lang/objc/ivar-IMP/TestObjCiVarIMP.py
@@ -0,0 +1,75 @@
+"""
+Test that dynamically discovered ivars of type IMP do not crash LLDB
+"""
+
+import os, time
+import re
+import unittest2
+import lldb, lldbutil
+from lldbtest import *
+import commands
+
+def execute_command (command):
+ # print '%% %s' % (command)
+ (exit_status, output) = commands.getstatusoutput (command)
+ # if output:
+ # print output
+ # print 'status = %u' % (exit_status)
+ return exit_status
+
+class ObjCiVarIMPTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipUnlessDarwin
+ 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")
+ self.buildReproCase()
+ self.runTheTest()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+
+ def buildReproCase (self):
+ execute_command("make repro")
+
+ def runTheTest(self):
+ """MakeTest that dynamically discovered ivars of type IMP do not crash LLDB"""
+ 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]'
+ ])
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
diff --git a/lldb/test/lang/objc/ivar-IMP/myclass.h b/lldb/test/lang/objc/ivar-IMP/myclass.h
new file mode 100644
index 0000000..da28d1e
--- /dev/null
+++ b/lldb/test/lang/objc/ivar-IMP/myclass.h
@@ -0,0 +1,6 @@
+#import <Foundation/Foundation.h>
+
+@interface MyClass : NSObject
+{}
+- (id)init;
+@end
diff --git a/lldb/test/lang/objc/ivar-IMP/myclass.m b/lldb/test/lang/objc/ivar-IMP/myclass.m
new file mode 100644
index 0000000..3ff2ac7
--- /dev/null
+++ b/lldb/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/lldb/test/lang/objc/ivar-IMP/repro.m b/lldb/test/lang/objc/ivar-IMP/repro.m
new file mode 100644
index 0000000..dc522b2
--- /dev/null
+++ b/lldb/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
+}