summaryrefslogtreecommitdiff
path: root/lib/builtins/os_version_check.c
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2017-03-14 17:53:37 +0000
committerAlex Lorenz <arphaman@gmail.com>2017-03-14 17:53:37 +0000
commit38d71b5b496882878eed03bb3f741af2797fa83c (patch)
tree4e861213392200fef6c8b6d5d02777ee5b8ec2ed /lib/builtins/os_version_check.c
parentd112f65e1dd555f069e8f3e33ab3dafbacb5435b (diff)
[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 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@297760 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/builtins/os_version_check.c')
-rw-r--r--lib/builtins/os_version_check.c85
1 files changed, 68 insertions, 17 deletions
diff --git a/lib/builtins/os_version_check.c b/lib/builtins/os_version_check.c
index b36ae546e..fd8a96ae2 100644
--- a/lib/builtins/os_version_check.c
+++ b/lib/builtins/os_version_check.c
@@ -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 DispatchOnceCounter;
/* 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 *Unused) {
/* 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);
}