diff options
author | Alex Lorenz <arphaman@gmail.com> | 2017-03-14 17:53:37 +0000 |
---|---|---|
committer | Alex Lorenz <arphaman@gmail.com> | 2017-03-14 17:53:37 +0000 |
commit | 38d71b5b496882878eed03bb3f741af2797fa83c (patch) | |
tree | 4e861213392200fef6c8b6d5d02777ee5b8ec2ed /lib/builtins/os_version_check.c | |
parent | d112f65e1dd555f069e8f3e33ab3dafbacb5435b (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.c | 85 |
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); } |