[compiler-rt] r297760 - [compiler-rt][builtins] __isOSVersionAtLeast should load CoreFoundation

Alex Lorenz via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 14 10:53:37 PDT 2017


Author: arphaman
Date: Tue Mar 14 12:53:37 2017
New Revision: 297760

URL: http://llvm.org/viewvc/llvm-project?rev=297760&view=rev
Log:
[compiler-rt][builtins] __isOSVersionAtLeast should load CoreFoundation
symbols dynamically

The CoreFoundation symbols uses by __isOSVersionAtLeast should be loaded at
runtime to ensure that the programs that don't use @available won't have to be
linked to CoreFoundation.

The Clang frontend IRGen library will need to emit a CoreFoundation symbol
when @available is used to ensure that programs that actually use @available
are linked to CoreFoundation.

rdar://31039554

Added:
    compiler-rt/trunk/test/builtins/TestCases/Darwin/os_version_check_test_no_core_foundation.c
Modified:
    compiler-rt/trunk/lib/builtins/os_version_check.c

Modified: compiler-rt/trunk/lib/builtins/os_version_check.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/os_version_check.c?rev=297760&r1=297759&r2=297760&view=diff
==============================================================================
--- compiler-rt/trunk/lib/builtins/os_version_check.c (original)
+++ compiler-rt/trunk/lib/builtins/os_version_check.c Tue Mar 14 12:53:37 2017
@@ -18,6 +18,7 @@
 #include <CoreFoundation/CoreFoundation.h>
 #include <dispatch/dispatch.h>
 #include <TargetConditionals.h>
+#include <dlfcn.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -30,6 +31,55 @@ static dispatch_once_t DispatchOnceCount
 /* Find and parse the SystemVersion.plist file. */
 static void parseSystemVersionPList(void *Unused) {
   (void)Unused;
+  /* Load CoreFoundation dynamically */
+  const void *NullAllocator = dlsym(RTLD_DEFAULT, "kCFAllocatorNull");
+  if (!NullAllocator)
+    return;
+  const CFAllocatorRef kCFAllocatorNull =
+      *(const CFAllocatorRef *)NullAllocator;
+  typeof(CFDataCreateWithBytesNoCopy) *CFDataCreateWithBytesNoCopyFunc =
+      (typeof(CFDataCreateWithBytesNoCopy) *)dlsym(
+          RTLD_DEFAULT, "CFDataCreateWithBytesNoCopy");
+  if (!CFDataCreateWithBytesNoCopyFunc)
+    return;
+  typeof(CFPropertyListCreateWithData) *CFPropertyListCreateWithDataFunc =
+      (typeof(CFPropertyListCreateWithData) *)dlsym(
+          RTLD_DEFAULT, "CFPropertyListCreateWithData");
+  /* CFPropertyListCreateWithData was introduced only in macOS 10.6+, so it
+   * will be NULL on earlier OS versions. */
+  typeof(CFPropertyListCreateFromXMLData) *CFPropertyListCreateFromXMLDataFunc =
+      (typeof(CFPropertyListCreateFromXMLData) *)dlsym(
+          RTLD_DEFAULT, "CFPropertyListCreateFromXMLData");
+  /* CFPropertyListCreateFromXMLDataFunc is deprecated in macOS 10.10, so it
+   * might be NULL in future OS versions. */
+  if (!CFPropertyListCreateWithDataFunc && !CFPropertyListCreateFromXMLDataFunc)
+    return;
+  typeof(CFStringCreateWithCStringNoCopy) *CFStringCreateWithCStringNoCopyFunc =
+      (typeof(CFStringCreateWithCStringNoCopy) *)dlsym(
+          RTLD_DEFAULT, "CFStringCreateWithCStringNoCopy");
+  if (!CFStringCreateWithCStringNoCopyFunc)
+    return;
+  typeof(CFDictionaryGetValue) *CFDictionaryGetValueFunc =
+      (typeof(CFDictionaryGetValue) *)dlsym(RTLD_DEFAULT,
+                                            "CFDictionaryGetValue");
+  if (!CFDictionaryGetValueFunc)
+    return;
+  typeof(CFGetTypeID) *CFGetTypeIDFunc =
+      (typeof(CFGetTypeID) *)dlsym(RTLD_DEFAULT, "CFGetTypeID");
+  if (!CFGetTypeIDFunc)
+    return;
+  typeof(CFStringGetTypeID) *CFStringGetTypeIDFunc =
+      (typeof(CFStringGetTypeID) *)dlsym(RTLD_DEFAULT, "CFStringGetTypeID");
+  if (!CFStringGetTypeIDFunc)
+    return;
+  typeof(CFStringGetCString) *CFStringGetCStringFunc =
+      (typeof(CFStringGetCString) *)dlsym(RTLD_DEFAULT, "CFStringGetCString");
+  if (!CFStringGetCStringFunc)
+    return;
+  typeof(CFRelease) *CFReleaseFunc =
+      (typeof(CFRelease) *)dlsym(RTLD_DEFAULT, "CFRelease");
+  if (!CFReleaseFunc)
+    return;
 
   char *PListPath = "/System/Library/CoreServices/SystemVersion.plist";
 
@@ -67,40 +117,41 @@ static void parseSystemVersionPList(void
 
   /* Get the file buffer into CF's format. We pass in a null allocator here *
    * because we free PListBuf ourselves */
-  FileContentsRef = CFDataCreateWithBytesNoCopy(
+  FileContentsRef = (*CFDataCreateWithBytesNoCopyFunc)(
       NULL, PListBuf, (CFIndex)NumRead, kCFAllocatorNull);
   if (!FileContentsRef)
     goto Fail;
 
-  if (&CFPropertyListCreateWithData)
-    PListRef = CFPropertyListCreateWithData(
+  if (CFPropertyListCreateWithDataFunc)
+    PListRef = (*CFPropertyListCreateWithDataFunc)(
         NULL, FileContentsRef, kCFPropertyListImmutable, NULL, NULL);
-  else {
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-    PListRef = CFPropertyListCreateFromXMLData(NULL, FileContentsRef,
-                                               kCFPropertyListImmutable, NULL);
-#pragma clang diagnostic pop
-  }
+  else
+    PListRef = (*CFPropertyListCreateFromXMLDataFunc)(
+        NULL, FileContentsRef, kCFPropertyListImmutable, NULL);
   if (!PListRef)
     goto Fail;
 
-  CFTypeRef OpaqueValue =
-      CFDictionaryGetValue(PListRef, CFSTR("ProductVersion"));
-  if (!OpaqueValue || CFGetTypeID(OpaqueValue) != CFStringGetTypeID())
+  CFStringRef ProductVersion = (*CFStringCreateWithCStringNoCopyFunc)(
+      NULL, "ProductVersion", kCFStringEncodingASCII, kCFAllocatorNull);
+  if (!ProductVersion)
+    goto Fail;
+  CFTypeRef OpaqueValue = (*CFDictionaryGetValueFunc)(PListRef, ProductVersion);
+  (*CFReleaseFunc)(ProductVersion);
+  if (!OpaqueValue ||
+      (*CFGetTypeIDFunc)(OpaqueValue) != (*CFStringGetTypeIDFunc)())
     goto Fail;
 
   char VersionStr[32];
-  if (!CFStringGetCString((CFStringRef)OpaqueValue, VersionStr,
-                          sizeof(VersionStr), kCFStringEncodingUTF8))
+  if (!(*CFStringGetCStringFunc)((CFStringRef)OpaqueValue, VersionStr,
+                                 sizeof(VersionStr), kCFStringEncodingUTF8))
     goto Fail;
   sscanf(VersionStr, "%d.%d.%d", &GlobalMajor, &GlobalMinor, &GlobalSubminor);
 
 Fail:
   if (PListRef)
-    CFRelease(PListRef);
+    (*CFReleaseFunc)(PListRef);
   if (FileContentsRef)
-    CFRelease(FileContentsRef);
+    (*CFReleaseFunc)(FileContentsRef);
   free(PListBuf);
   fclose(PropertyList);
 }

Added: compiler-rt/trunk/test/builtins/TestCases/Darwin/os_version_check_test_no_core_foundation.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/builtins/TestCases/Darwin/os_version_check_test_no_core_foundation.c?rev=297760&view=auto
==============================================================================
--- compiler-rt/trunk/test/builtins/TestCases/Darwin/os_version_check_test_no_core_foundation.c (added)
+++ compiler-rt/trunk/test/builtins/TestCases/Darwin/os_version_check_test_no_core_foundation.c Tue Mar 14 12:53:37 2017
@@ -0,0 +1,12 @@
+// RUN: %clang %s -o %t -mmacosx-version-min=10.5
+// RUN: %run %t
+
+int __isOSVersionAtLeast(int Major, int Minor, int Subminor);
+
+int main() {
+  // When CoreFoundation isn't linked, we expect the system version to be 0, 0,
+  // 0.
+  if (__isOSVersionAtLeast(1, 0, 0))
+    return 1;
+  return 0;
+}




More information about the llvm-commits mailing list