sgraenitz created this revision.
sgraenitz added reviewers: theraven, triplef, mgorny, labath, omjavaid, 
xiaobai, aleksandr.urakov, zturner.
Herald added a project: All.
sgraenitz requested review of this revision.
Herald added a project: LLDB.

We are planning to add basic ObjC debug support for the GNUstep ObjC runtime on 
Linux and Windows: https://github.com/gnustep/libobjc2 On Linux much of the 
desired functionality is there already. It seems accidental in parts, but it's 
a good early baseline. On Windows nothing works yet.

In this first patch I want to add the necessary test infrastructure to utilize 
the GNUstep runtime in the LLDB test suite. The minimal test demonstrates that 
it works on Linux. The next goal is to extend the PDB parser and get Windows to 
this baseline as well.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D146058

Files:
  lldb/test/CMakeLists.txt
  lldb/test/Shell/Expr/objc-gnustep-print.m
  lldb/test/Shell/helper/build.py
  lldb/test/Shell/helper/toolchain.py
  lldb/test/Shell/lit.cfg.py
  lldb/test/Shell/lit.site.cfg.py.in

Index: lldb/test/Shell/lit.site.cfg.py.in
===================================================================
--- lldb/test/Shell/lit.site.cfg.py.in
+++ lldb/test/Shell/lit.site.cfg.py.in
@@ -16,6 +16,7 @@
 config.target_triple = "@LLVM_TARGET_TRIPLE@"
 config.python_executable = "@Python3_EXECUTABLE@"
 config.have_zlib = @LLVM_ENABLE_ZLIB@
+config.objc_gnustep_dir = "@LLDB_TEST_OBJC_GNUSTEP_DIR@"
 config.lldb_enable_lzma = @LLDB_ENABLE_LZMA@
 config.host_triple = "@LLVM_HOST_TRIPLE@"
 config.lldb_bitness = 64 if @LLDB_IS_64_BITS@ else 32
Index: lldb/test/Shell/lit.cfg.py
===================================================================
--- lldb/test/Shell/lit.cfg.py
+++ lldb/test/Shell/lit.cfg.py
@@ -24,7 +24,7 @@
 
 # suffixes: A list of file extensions to treat as test files. This is overriden
 # by individual lit.local.cfg files in the test subdirectories.
-config.suffixes = ['.test', '.cpp', '.s']
+config.suffixes = ['.test', '.cpp', '.s', '.m']
 
 # excludes: A list of directories to exclude from the testsuite. The 'Inputs'
 # subdirectories contain auxiliary inputs for various tests in their parent
@@ -135,6 +135,14 @@
 if config.have_lldb_server:
     config.available_features.add('lldb-server')
 
+if config.objc_gnustep_dir:
+    config.available_features.add('objc-gnustep')
+    if platform.system() == 'Windows':
+        # objc.dll must be in PATH since Windows has no rpath
+        config.environment['PATH'] = os.path.pathsep.join((
+            os.path.join(config.objc_gnustep_dir, 'lib'),
+            config.environment.get('PATH','')))
+
 # NetBSD permits setting dbregs either if one is root
 # or if user_set_dbregs is enabled
 can_set_dbregs = True
Index: lldb/test/Shell/helper/toolchain.py
===================================================================
--- lldb/test/Shell/helper/toolchain.py
+++ lldb/test/Shell/helper/toolchain.py
@@ -42,6 +42,8 @@
         build_script_args.append('--tools-dir={0}'.format(config.lldb_tools_dir))
     if config.llvm_libs_dir:
         build_script_args.append('--libs-dir={0}'.format(config.llvm_libs_dir))
+    if config.objc_gnustep_dir:
+        build_script_args.append('--objc-gnustep-dir="{0}"'.format(config.objc_gnustep_dir))
 
     lldb_init = _get_lldb_init_path(config)
 
Index: lldb/test/Shell/helper/build.py
===================================================================
--- lldb/test/Shell/helper/build.py
+++ lldb/test/Shell/helper/build.py
@@ -49,6 +49,18 @@
                     action='append',
                     help='If specified, a path to search in addition to PATH when --compiler is not an exact path')
 
+parser.add_argument('--objc-gnustep-dir',
+                    metavar='directory',
+                    dest='objc_gnustep_dir',
+                    required=False,
+                    help='If specified, a path to GNUstep libobjc2 runtime for use on Windows and Linux')
+
+parser.add_argument('--objc-gnustep',
+                    dest='objc_gnustep',
+                    action='store_true',
+                    default=False,
+                    help='Windows and Linux include/link GNUstep libobjc2 for this build')
+
 if sys.platform == 'darwin':
     parser.add_argument('--apple-sdk',
                         metavar='apple_sdk',
@@ -238,6 +250,10 @@
         self.obj_ext = obj_ext
         self.lib_paths = args.libs_dir
         self.std = args.std
+        if args.objc_gnustep:
+            assert args.objc_gnustep_dir, "GNUstep libobjc2 runtime for Linux and Windows"
+            self.objc_gnustep_inc = os.path.join(args.objc_gnustep_dir, 'include')
+            self.objc_gnustep_lib = os.path.join(args.objc_gnustep_dir, 'lib')
 
     def _exe_file_name(self):
         assert self.mode != 'compile'
@@ -656,15 +672,20 @@
             args.append('-static')
         args.append('-c')
 
-        args.extend(['-o', obj])
-        args.append(source)
-
         if sys.platform == 'darwin':
             args.extend(['-isysroot', self.apple_sdk])
+        elif self.objc_gnustep_inc:
+            if source.endswith('.m') or source.endswith('.mm'):
+                args.extend(['-fobjc-runtime=gnustep-2.0', '-I', self.objc_gnustep_inc])
+                if sys.platform == "win32":
+                    args.extend(['-Xclang', '-gcodeview', '-Xclang', '--dependent-lib=msvcrtd'])
 
         if self.std:
             args.append('-std={0}'.format(self.std))
 
+        args.extend(['-o', obj])
+        args.append(source)
+
         return ('compiling', [source], obj, None, args)
 
     def _get_link_command(self):
@@ -686,6 +707,12 @@
 
         if sys.platform == 'darwin':
             args.extend(['-isysroot', self.apple_sdk])
+        elif self.objc_gnustep_lib:
+            args.extend(['-L', self.objc_gnustep_lib, '-lobjc'])
+            if sys.platform == 'linux':
+                args.extend(['-Wl,-rpath,' + self.objc_gnustep_lib])
+            elif sys.platform == 'win32':
+                args.extend(['-fuse-ld=lld-link', '-g', '-Xclang', '--dependent-lib=msvcrtd'])
 
         return ('linking', self._obj_file_names(), self._exe_file_name(), None, args)
 
Index: lldb/test/Shell/Expr/objc-gnustep-print.m
===================================================================
--- /dev/null
+++ lldb/test/Shell/Expr/objc-gnustep-print.m
@@ -0,0 +1,60 @@
+// REQUIRES: objc-gnustep
+// XFAIL: system-windows
+//
+// RUN: %build %s --compiler=clang --objc-gnustep --output=%t
+// RUN: %lldb -b -o "b objc-gnustep-print.m:35" -o "run" -o "p self" -o "p *self" -- %t | FileCheck %s
+
+#import "objc/runtime.h"
+
+@protocol NSCoding
+@end
+
+#ifdef __has_attribute
+#if __has_attribute(objc_root_class)
+__attribute__((objc_root_class))
+#endif
+#endif
+@interface NSObject <NSCoding> {
+	id isa;
+	int refcount;
+}
+@end
+@implementation NSObject
+- (id)class {
+	return object_getClass(self);
+}
++ (id)new {
+	return class_createInstance(self, 0);
+}
+@end
+@interface TestObj : NSObject {}
+- (int)ok;
+@end
+@implementation TestObj
+- (int)ok {
+	return self ? 0 : 1;
+}
+@end
+
+// CHECK: (lldb) b objc-gnustep-print.m:35
+// CHECK: Breakpoint {{.*}} at objc-gnustep-print.m
+//
+// CHECK: (lldb) run
+// CHECK: Process {{[0-9]+}} stopped
+// CHECK: -[TestObj ok](self=[[SELF_PTR:0x[0-9]+]]{{.*}}) at objc-gnustep-print.m:35
+//
+// CHECK: (lldb) p self
+// CHECK: (TestObj *) $0 = [[SELF_PTR]]
+//
+// CHECK: (lldb) p *self
+// CHECK: (TestObj) $1 = {
+// CHECK:   NSObject = {
+// CHECK:     isa
+// CHECK:     refcount
+// CHECK:   }
+// CHECK: }
+
+int main() {
+	TestObj *testObj = [TestObj new];
+	return [testObj ok];
+}
Index: lldb/test/CMakeLists.txt
===================================================================
--- lldb/test/CMakeLists.txt
+++ lldb/test/CMakeLists.txt
@@ -25,6 +25,20 @@
 file(MAKE_DIRECTORY ${LLDB_TEST_MODULE_CACHE_LLDB})
 file(MAKE_DIRECTORY ${LLDB_TEST_MODULE_CACHE_CLANG})
 
+# Windows and Linux have no built-in ObjC runtime. Let the user provide a path and use GNUstep.
+if (UNIX AND NOT APPLE)
+  find_path(gnustep_install_dir NAMES lib/libobjc.so include/objc/runtime.h)
+  set(gnustep_info lib/libobjc.so)
+elseif (WIN32 AND EXISTS "C:/Program Files (x86)/libobjc/lib/objc.dll"
+              AND EXISTS "C:/Program Files (x86)/libobjc/include/objc/runtime.h")
+  set(gnustep_install_dir "C:/Program Files (x86)/libobjc")
+  set(gnustep_info lib/objc.dll)
+endif()
+set(LLDB_TEST_OBJC_GNUSTEP_DIR "${gnustep_install_dir}" CACHE PATH "GNUstep libobjc2 path for ObjC tests on Windows and Linux")
+if (LLDB_TEST_OBJC_GNUSTEP_DIR)
+  message(STATUS "Found GNUstep ObjC runtime: ${LLDB_TEST_OBJC_GNUSTEP_DIR}/${gnustep_info}")
+endif()
+
 # LLVM_BUILD_MODE is used in lit.site.cfg
 if (CMAKE_CFG_INTDIR STREQUAL ".")
   set(LLVM_BUILD_MODE ".")
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to