/ CFBundle_Binary.c
CFBundle_Binary.c
  1  /*
  2   * Copyright (c) 2015 Apple Inc. All rights reserved.
  3   *
  4   * @APPLE_LICENSE_HEADER_START@
  5   *
  6   * This file contains Original Code and/or Modifications of Original Code
  7   * as defined in and that are subject to the Apple Public Source License
  8   * Version 2.0 (the 'License'). You may not use this file except in
  9   * compliance with the License. Please obtain a copy of the License at
 10   * http://www.opensource.apple.com/apsl/ and read it before using this
 11   * file.
 12   *
 13   * The Original Code and all software distributed under the License are
 14   * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 15   * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 16   * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 17   * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 18   * Please see the License for the specific language governing rights and
 19   * limitations under the License.
 20   *
 21   * @APPLE_LICENSE_HEADER_END@
 22   */
 23  
 24  /*      CFBundle_Binary.c
 25          Copyright (c) 1999-2014, Apple Inc.  All rights reserved.
 26          Responsibility: Tony Parker
 27  */
 28  
 29  #include "CFBundle_Internal.h"
 30  
 31  #if defined(BINARY_SUPPORT_DYLD)
 32  // Import the mach-o headers that define the macho magic numbers
 33  #include <mach-o/loader.h>
 34  #include <mach-o/fat.h>
 35  #include <mach-o/arch.h>
 36  #include <mach-o/dyld.h>
 37  #include <mach-o/getsect.h>
 38  #include <unistd.h>
 39  #include <fcntl.h>
 40  #include <sys/mman.h>
 41  #include <crt_externs.h>
 42  #if defined(USE_DYLD_PRIV)
 43  #include <mach-o/dyld_priv.h>
 44  #endif /* USE_DYLD_PRIV */
 45  #endif /* BINARY_SUPPORT_DYLD */
 46  
 47  #if defined(BINARY_SUPPORT_DLFCN)
 48  #include <dlfcn.h>
 49  #endif /* BINARY_SUPPORT_DLFCN */
 50  
 51  #if defined(BINARY_SUPPORT_DYLD)
 52  static CFStringRef _CFBundleDYLDCopyLoadedImagePathForPointer(void *p);
 53  #if !defined(BINARY_SUPPORT_DLFCN)
 54  static void *_CFBundleDYLDGetSymbolByNameWithSearch(CFBundleRef bundle, CFStringRef symbolName, Boolean globalSearch);
 55  #endif /* !BINARY_SUPPORT_DLFCN */
 56  #endif /* BINARY_SUPPORT_DYLD */
 57  #if defined(BINARY_SUPPORT_DLFCN)
 58  static void *_CFBundleDlfcnGetSymbolByNameWithSearch(CFBundleRef bundle, CFStringRef symbolName, Boolean globalSearch);
 59  #if !defined(BINARY_SUPPORT_DYLD)
 60  static CFStringRef _CFBundleDlfcnCopyLoadedImagePathForPointer(void *p);
 61  #endif /* !BINARY_SUPPORT_DYLD */
 62  #endif /* BINARY_SUPPORT_DLFCN */
 63  
 64  
 65  CF_PRIVATE SInt32 _CFBundleCurrentArchitecture(void) {
 66      SInt32 arch = 0;
 67  #if defined(__ppc__)
 68      arch = kCFBundleExecutableArchitecturePPC;
 69  #elif defined(__ppc64__)
 70      arch = kCFBundleExecutableArchitecturePPC64;
 71  #elif defined(__i386__)
 72      arch = kCFBundleExecutableArchitectureI386;
 73  #elif defined(__x86_64__)
 74      arch = kCFBundleExecutableArchitectureX86_64;
 75  #elif defined(BINARY_SUPPORT_DYLD)
 76      const NXArchInfo *archInfo = NXGetLocalArchInfo();
 77      if (archInfo) arch = archInfo->cputype;
 78  #endif
 79      return arch;
 80  }
 81  
 82  #if defined(BINARY_SUPPORT_DYLD)
 83  
 84  CF_PRIVATE CFArrayRef _CFBundleDYLDCopyLoadedImagePathsForHint(CFStringRef hint) {
 85      uint32_t i, numImages = _dyld_image_count();
 86      CFMutableArrayRef result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
 87      CFRange range = CFRangeMake(0, CFStringGetLength(hint)), altRange = CFRangeMake(0, 0), testRange = CFRangeMake(0, 0);
 88      const char *processPath = _CFProcessPath();
 89      const void *mhp = (const void *)_NSGetMachExecuteHeader();
 90      
 91      if (range.length > 14) {
 92          // handle some common variations on framework bundle identifiers
 93          if (CFStringFindWithOptions(hint, CFSTR(".framework"), range, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, &testRange) && testRange.location > 0 && testRange.length > 0) {
 94              // identifier has .framework appended
 95              altRange.length = testRange.location;
 96          } else if (CFStringFindWithOptions(hint, CFSTR("framework"), range, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, &testRange) && testRange.location > 0 && testRange.length > 0) {
 97              // identifier has Framework appended
 98              altRange.length = testRange.location;
 99          } else if (CFStringFindWithOptions(hint, CFSTR("fw"), range, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, &testRange) && testRange.location > 0 && testRange.length > 0) {
100              // identifier has FW appended
101              altRange.length = testRange.location;
102          }
103      }
104      for (i = 0; i < numImages; i++) {
105          const char *curName = _dyld_get_image_name(i), *lastComponent = NULL;
106          if (curName && (!processPath || 0 != strcmp(curName, processPath)) && mhp != (void *)_dyld_get_image_header(i)) lastComponent = strrchr(curName, '/');
107          if (lastComponent) {
108              CFStringRef str = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, lastComponent + 1);
109              if (str) {
110                  if (CFStringFindWithOptions(hint, str, range, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, NULL) || (altRange.length > 0 && CFStringFindWithOptions(hint, str, altRange, kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, NULL))) {
111                      CFStringRef curStr = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, curName);
112                      if (curStr) {
113                          CFArrayAppendValue(result, curStr);
114                          CFRelease(curStr);
115                      }
116                  }
117                  CFRelease(str);
118              }
119          }
120      }
121      return result;
122  }
123  
124  static char *_cleanedPathForPath(const char *curName) {
125      char *thePath = strdup(curName);
126      if (thePath) {
127          // We are going to process the buffer replacing all "/./" and "//" with "/"
128          CFIndex srcIndex = 0, dstIndex = 0;
129          CFIndex len = strlen(thePath);
130          for (srcIndex=0; srcIndex<len; srcIndex++) {
131              thePath[dstIndex] = thePath[srcIndex];
132              dstIndex++;
133              while (srcIndex < len-1 && thePath[srcIndex] == '/' && (thePath[srcIndex+1] == '/' || (thePath[srcIndex+1] == '.' && srcIndex < len-2 && thePath[srcIndex+2] == '/'))) srcIndex += (thePath[srcIndex+1] == '/' ? 1 : 2);
134          }
135          thePath[dstIndex] = 0;
136      }
137      return thePath;
138  }
139  
140  CF_PRIVATE CFArrayRef _CFBundleDYLDCopyLoadedImagePathsIfChanged(void) {
141      // This returns an array of the paths of all the dyld images in the process.  These paths may not be absolute, they may point at things that are not bundles, they may be staticly linked bundles or dynamically loaded bundles, they may be NULL.
142      uint32_t i, numImages = _dyld_image_count();
143      CFMutableArrayRef result = NULL;
144      static uint32_t _cachedDYLDImageCount = -1;
145  
146      if (numImages != _cachedDYLDImageCount) {
147          const char *curName;
148          char *cleanedCurName = NULL;
149          CFStringRef curStr;
150          const char *processPath = _CFProcessPath();
151          const void *mhp = (const void *)_NSGetMachExecuteHeader();
152  
153          result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
154  
155          for (i = 0; i < numImages; i++) {
156              curName = _dyld_get_image_name(i);
157              if (curName && i == 0) cleanedCurName = _cleanedPathForPath(curName);
158              if (curName && (!processPath || 0 != strcmp(curName, processPath)) && (!processPath || !cleanedCurName || 0 != strcmp(cleanedCurName, processPath)) && mhp != (void *)_dyld_get_image_header(i)) {
159                  curStr = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, curName);
160                  if (curStr) {
161                      CFArrayAppendValue(result, curStr);
162                      CFRelease(curStr);
163                  }
164              }
165              if (cleanedCurName) {
166                  free(cleanedCurName);
167                  cleanedCurName = NULL;
168              }
169          }
170          _cachedDYLDImageCount = numImages;
171      }
172      return result;
173  }
174  
175  static CFStringRef _CFBundleDYLDCopyLoadedImagePathForPointer(void *p) {
176      CFStringRef result = NULL;
177  #if defined(USE_DYLD_PRIV)
178      const char *name = dyld_image_path_containing_address(p);
179      if (name) result = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, name);
180  #else /* USE_DYLD_PRIV */
181      if (!result) {
182          uint32_t i, j, n = _dyld_image_count();
183          Boolean foundit = false;
184          const char *name;
185  #if __LP64__
186  #define MACH_HEADER_TYPE struct mach_header_64
187  #define MACH_SEGMENT_CMD_TYPE struct segment_command_64
188  #define MACH_SEGMENT_FLAVOR LC_SEGMENT_64
189  #else
190  #define MACH_HEADER_TYPE struct mach_header
191  #define MACH_SEGMENT_CMD_TYPE struct segment_command
192  #define MACH_SEGMENT_FLAVOR LC_SEGMENT
193  #endif
194          for (i = 0; !foundit && i < n; i++) {
195              const MACH_HEADER_TYPE *mh = (const MACH_HEADER_TYPE *)_dyld_get_image_header(i);
196              uintptr_t addr = (uintptr_t)p - _dyld_get_image_vmaddr_slide(i);
197              if (mh) {
198                  struct load_command *lc = (struct load_command *)((char *)mh + sizeof(MACH_HEADER_TYPE));
199                  for (j = 0; !foundit && j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) {
200                      if (MACH_SEGMENT_FLAVOR == lc->cmd && ((MACH_SEGMENT_CMD_TYPE *)lc)->vmaddr <= addr && addr < ((MACH_SEGMENT_CMD_TYPE *)lc)->vmaddr + ((MACH_SEGMENT_CMD_TYPE *)lc)->vmsize) {
201                          foundit = true;
202                          name = _dyld_get_image_name(i);
203                          if (name) result = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, name);
204                      }
205                  }
206              }
207          }
208  #undef MACH_HEADER_TYPE
209  #undef MACH_SEGMENT_CMD_TYPE
210  #undef MACH_SEGMENT_FLAVOR
211      }
212  #endif /* USE_DYLD_PRIV */
213  #if LOG_BUNDLE_LOAD
214      printf("dyld image path for pointer %p is %p\n", p, result);
215  #endif /* LOG_BUNDLE_LOAD */
216      return result;
217  }
218  
219  #if !defined(BINARY_SUPPORT_DLFCN) 
220  
221  static const void *__CFBundleDYLDFindImage(char *buff) {
222      const void *header = NULL;
223      uint32_t i, numImages = _dyld_image_count(), numMatches = 0;
224      const char *curName, *p, *q;
225  
226      for (i = 0; !header && i < numImages; i++) {
227          curName = _dyld_get_image_name(i);
228          if (curName && 0 == strncmp(curName, buff, CFMaxPathSize)) {
229              header = _dyld_get_image_header(i);
230              numMatches = 1;
231          }
232      }
233      if (!header) {
234          for (i = 0; i < numImages; i++) {
235              curName = _dyld_get_image_name(i);
236              if (curName) {
237                  for (p = buff, q = curName; *p && *q && (q - curName < CFMaxPathSize); p++, q++) {
238                      if (*p != *q && (q - curName > 11) && 0 == strncmp(q - 11, ".framework/Versions/", 20) && *(q + 9) && '/' == *(q + 10)) q += 11;
239                      else if (*p != *q && (q - curName > 12) && 0 == strncmp(q - 12, ".framework/Versions/", 20) && *(q + 8) && '/' == *(q + 9)) q += 10;
240                      if (*p != *q) break;
241                  }
242                  if (*p == *q) {
243                      header = _dyld_get_image_header(i);
244                      numMatches++;
245                  }
246              }
247          }
248      }
249      return (numMatches == 1) ? header : NULL;
250  }
251  
252  CF_PRIVATE Boolean _CFBundleDYLDCheckLoaded(CFBundleRef bundle) {
253      if (!bundle->_isLoaded) {
254          CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
255          char buff[CFMaxPathSize];
256  
257          if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) {
258              const void *header = __CFBundleDYLDFindImage(buff);
259              if (header) {
260                  if (bundle->_binaryType == __CFBundleUnknownBinary) bundle->_binaryType = __CFBundleDYLDFrameworkBinary;
261                  if (!bundle->_imageCookie) {
262                      bundle->_imageCookie = header;
263  #if LOG_BUNDLE_LOAD
264                      printf("dyld check load bundle %p, find %s getting image %p\n", bundle, buff, bundle->_imageCookie);
265  #endif /* LOG_BUNDLE_LOAD */
266                  }
267                  bundle->_isLoaded = true;
268              } else {
269  #if LOG_BUNDLE_LOAD
270                  printf("dyld check load bundle %p, find %s no image\n", bundle, buff);
271  #endif /* LOG_BUNDLE_LOAD */
272              }
273          }
274          if (executableURL) CFRelease(executableURL);
275      }
276      return bundle->_isLoaded;
277  }
278  
279  CF_PRIVATE Boolean _CFBundleDYLDLoadBundle(CFBundleRef bundle, Boolean forceGlobal, CFErrorRef *error) {
280      CFErrorRef localError = NULL, *subError = (error ? &localError : NULL);
281      NSLinkEditErrors c = NSLinkEditUndefinedError;
282      int errorNumber = 0;
283      const char *fileName = NULL;
284      const char *errorString = NULL;
285  
286      if (!bundle->_isLoaded) {
287          CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
288          char buff[CFMaxPathSize];
289  
290          if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) {
291              NSObjectFileImage image;
292              NSObjectFileImageReturnCode retCode = NSCreateObjectFileImageFromFile(buff, &image);
293  #if LOG_BUNDLE_LOAD
294              printf("dyld load bundle %p, create image of %s returns image %p retcode %d\n", bundle, buff, image, retCode);
295  #endif /* LOG_BUNDLE_LOAD */
296              if (retCode == NSObjectFileImageSuccess) {
297                  uint32_t options = forceGlobal ? NSLINKMODULE_OPTION_RETURN_ON_ERROR : (NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
298                  NSModule module = NSLinkModule(image, buff, options);
299  #if LOG_BUNDLE_LOAD
300                  printf("dyld load bundle %p, link module of %s options 0x%x returns module %p image %p\n", bundle, buff, options, module, image);
301  #endif /* LOG_BUNDLE_LOAD */
302                  if (module) {
303                      bundle->_imageCookie = image;
304                      bundle->_moduleCookie = module;
305                      bundle->_isLoaded = true;
306                  } else {
307                      NSLinkEditError(&c, &errorNumber, &fileName, &errorString);
308                      if (error) {
309  #if defined(BINARY_SUPPORT_DLFCN)
310                          _CFBundleDlfcnPreflight(bundle, subError);
311  #endif /* BINARY_SUPPORT_DLFCN */
312                          if (!localError) {
313                              CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), debugString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("error code %d, error number %d (%@)"), c, errorNumber, tempString);
314                              localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString);
315                              if (tempString) CFRelease(tempString);
316                              if (debugString) CFRelease(debugString);
317                          }
318                      } else {
319                          CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), executableString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, fileName);
320                          CFLog(__kCFLogBundle, CFSTR("Error loading %@:  error code %d, error number %d (%@)"), executableString, c, errorNumber, tempString);
321                          if (tempString) CFRelease(tempString);
322                          if (executableString) CFRelease(executableString);
323                      }
324                      (void)NSDestroyObjectFileImage(image);
325                  }
326              } else {
327                  if (error) {
328                      if (retCode == NSObjectFileImageArch) {
329                          localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableArchitectureMismatchError);
330                      } else if (retCode == NSObjectFileImageInappropriateFile) {
331                          Boolean hasRuntimeMismatch = false;
332                          uint32_t mainFlags = 0, bundleFlags = 0;
333                          if (_CFBundleGrokObjCImageInfoFromMainExecutable(NULL, &mainFlags) && (mainFlags & 0x2) != 0) {
334                              if (_CFBundleGetObjCImageInfo(bundle, NULL, &bundleFlags) && (bundleFlags & 0x2) == 0) hasRuntimeMismatch = true;
335                          }
336                          if (hasRuntimeMismatch) {
337                              localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableRuntimeMismatchError);
338                          } else {
339                              localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotLoadableError);
340                          }
341                      } else {
342  #if defined(BINARY_SUPPORT_DLFCN)
343                          _CFBundleDlfcnPreflight(bundle, subError);
344  #endif /* BINARY_SUPPORT_DLFCN */
345                          if (!localError) {
346                              CFStringRef debugString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("dyld returns %d"), retCode);
347                              localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString);
348                              CFRelease(debugString);
349                          }
350                      }
351                  } else {
352                      CFLog(__kCFLogBundle, CFSTR("dyld returns %d when trying to load %@"), retCode, executableURL);
353                  }
354              }
355          } else {
356              if (error) {
357                  localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
358              } else {
359                  CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle);
360              }
361          }
362          if (executableURL) CFRelease(executableURL);
363      }
364      if (!bundle->_isLoaded && error) *error = localError;
365      return bundle->_isLoaded;
366  }
367  
368  CF_PRIVATE Boolean _CFBundleDYLDLoadFramework(CFBundleRef bundle, CFErrorRef *error) {
369      // !!! Framework loading should be better.  Can't unload frameworks.
370      CFErrorRef localError = NULL, *subError = (error ? &localError : NULL);
371      NSLinkEditErrors c = NSLinkEditUndefinedError;
372      int errorNumber = 0;
373      const char *fileName = NULL;
374      const char *errorString = NULL;
375  
376      if (!bundle->_isLoaded) {
377          CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
378          char buff[CFMaxPathSize];
379  
380          if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) {
381              void *image = (void *)NSAddImage(buff, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
382  #if LOG_BUNDLE_LOAD
383              printf("dyld load framework %p, add image of %s returns image %p\n", bundle, buff, image);
384  #endif /* LOG_BUNDLE_LOAD */
385              if (image) {
386                  bundle->_imageCookie = image;
387                  bundle->_isLoaded = true;
388              } else {
389                  NSLinkEditError(&c, &errorNumber, &fileName, &errorString);
390                  if (error) {
391  #if defined(BINARY_SUPPORT_DLFCN)
392                      _CFBundleDlfcnPreflight(bundle, subError);
393  #endif /* BINARY_SUPPORT_DLFCN */
394                      if (!localError) {
395                          CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), debugString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("error code %d, error number %d (%@)"), c, errorNumber, tempString);
396                          localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString);
397                          if (tempString) CFRelease(tempString);
398                          if (debugString) CFRelease(debugString);
399                      }
400                  } else {
401                      CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), executableString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, fileName);
402                      CFLog(__kCFLogBundle, CFSTR("Error loading %@:  error code %d, error number %d (%@)"), executableString, c, errorNumber, tempString);
403                      if (tempString) CFRelease(tempString);
404                      if (executableString) CFRelease(executableString);
405                  }
406              }
407          } else {
408              if (error) {
409                  localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
410              } else {
411                  CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle);
412              }
413          }
414          if (executableURL) CFRelease(executableURL);
415      }
416      if (!bundle->_isLoaded && error) *error = localError;
417      return bundle->_isLoaded;
418  }
419  
420  CF_PRIVATE void _CFBundleDYLDUnloadBundle(CFBundleRef bundle) {
421      if (bundle->_isLoaded) {
422  #if LOG_BUNDLE_LOAD
423          printf("dyld unload bundle %p, handle %p module %p image %p\n", bundle, bundle->_handleCookie, bundle->_moduleCookie, bundle->_imageCookie);
424  #endif /* LOG_BUNDLE_LOAD */
425          if (bundle->_moduleCookie && !NSUnLinkModule((NSModule)(bundle->_moduleCookie), NSUNLINKMODULE_OPTION_NONE)) {
426              CFLog(__kCFLogBundle, CFSTR("Internal error unloading bundle %@"), bundle);
427          } else {
428              if (bundle->_moduleCookie && bundle->_imageCookie) (void)NSDestroyObjectFileImage((NSObjectFileImage)(bundle->_imageCookie));
429              bundle->_connectionCookie = bundle->_handleCookie = NULL;
430              bundle->_imageCookie = bundle->_moduleCookie = NULL;
431              bundle->_isLoaded = false;
432          }
433      }
434  }
435  
436  CF_PRIVATE void *_CFBundleDYLDGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName) {
437      return _CFBundleDYLDGetSymbolByNameWithSearch(bundle, symbolName, false);
438  }
439  
440  static void *_CFBundleDYLDGetSymbolByNameWithSearch(CFBundleRef bundle, CFStringRef symbolName, Boolean globalSearch) {
441      void *result = NULL;
442      char buff[1026];
443      NSSymbol symbol = NULL;
444      
445      buff[0] = '_';
446      if (CFStringGetCString(symbolName, &(buff[1]), 1024, kCFStringEncodingUTF8)) {
447          if (bundle->_moduleCookie) {
448              symbol = NSLookupSymbolInModule((NSModule)(bundle->_moduleCookie), buff);
449          } else if (bundle->_imageCookie) {
450              symbol = NSLookupSymbolInImage(bundle->_imageCookie, buff, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND|NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
451          } 
452          if (!symbol && !bundle->_moduleCookie && (!bundle->_imageCookie || globalSearch)) {
453              char hintBuff[1026];
454              CFStringRef executableName = _CFBundleCopyExecutableName(bundle, NULL, NULL);
455              hintBuff[0] = '\0';
456              if (executableName) {
457                  if (!CFStringGetCString(executableName, hintBuff, 1024, kCFStringEncodingUTF8)) hintBuff[0] = '\0';
458                  CFRelease(executableName);
459              }
460              // Nowdays, NSIsSymbolNameDefinedWithHint() and NSLookupAndBindSymbolWithHint()
461              // are identical, except the first just returns a bool, so checking with the
462              // Is function first just causes a redundant lookup.
463              // This returns NULL on failure.
464              symbol = NSLookupAndBindSymbolWithHint(buff, hintBuff);
465          }
466          if (symbol) result = NSAddressOfSymbol(symbol);
467  #if defined(DEBUG)
468          if (!result) CFLog(__kCFLogBundle, CFSTR("dyld cannot find symbol %@ in %@"), symbolName, bundle);
469  #endif /* DEBUG */
470  #if LOG_BUNDLE_LOAD
471          printf("bundle %p handle %p module %p image %p dyld returns symbol %p for %s\n", bundle, bundle->_handleCookie, bundle->_moduleCookie, bundle->_imageCookie, result, buff + 1);
472  #endif /* LOG_BUNDLE_LOAD */
473      }
474      return result;
475  }
476  
477  #endif /* !BINARY_SUPPORT_DLFCN */
478  #endif /* BINARY_SUPPORT_DYLD */
479  
480  #if defined(BINARY_SUPPORT_DLFCN)
481  
482  CF_PRIVATE Boolean _CFBundleDlfcnCheckLoaded(CFBundleRef bundle) {
483      if (!bundle->_isLoaded) {
484          CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
485          char buff[CFMaxPathSize];
486  
487          if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) {
488              int mode = RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD | RTLD_FIRST;
489              void *handle = dlopen(buff, mode);
490              if (handle) {
491                  if (!bundle->_handleCookie) {
492                      bundle->_handleCookie = handle;
493  #if LOG_BUNDLE_LOAD
494                      printf("dlfcn check load bundle %p, dlopen of %s mode 0x%x getting handle %p\n", bundle, buff, mode, bundle->_handleCookie);
495  #endif /* LOG_BUNDLE_LOAD */
496                  }
497                  bundle->_isLoaded = true;
498              } else {
499  #if LOG_BUNDLE_LOAD
500                  printf("dlfcn check load bundle %p, dlopen of %s mode 0x%x no handle\n", bundle, buff, mode);
501  #endif /* LOG_BUNDLE_LOAD */
502              }
503          }
504          if (executableURL) CFRelease(executableURL);
505      }
506      return bundle->_isLoaded;
507  }
508  
509  CF_EXPORT Boolean _CFBundleDlfcnPreflight(CFBundleRef bundle, CFErrorRef *error) {
510      Boolean retval = true;
511      CFErrorRef localError = NULL;
512      if (!bundle->_isLoaded) {
513          CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
514          char buff[CFMaxPathSize];
515          
516          retval = false;
517          if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) {
518              retval = dlopen_preflight(buff);
519              if (!retval && error) {
520                  CFArrayRef archs = CFBundleCopyExecutableArchitectures(bundle);
521                  CFStringRef debugString = NULL;
522                  const char *errorString = dlerror();
523                  if (errorString && strlen(errorString) > 0) debugString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString);
524                  if (archs) {
525                      Boolean hasSuitableArch = false, hasRuntimeMismatch = false;
526                      CFIndex i, count = CFArrayGetCount(archs);
527                      SInt32 arch, curArch = _CFBundleCurrentArchitecture();
528                      for (i = 0; !hasSuitableArch && i < count; i++) {
529                          if (CFNumberGetValue((CFNumberRef)CFArrayGetValueAtIndex(archs, i), kCFNumberSInt32Type, (void *)&arch) && arch == curArch) hasSuitableArch = true;
530                      }
531  #if defined(BINARY_SUPPORT_DYLD)
532                      if (hasSuitableArch) {
533                          uint32_t mainFlags = 0;
534                          if (_CFBundleGrokObjCImageInfoFromMainExecutable(NULL, &mainFlags) && (mainFlags & 0x2) != 0) {
535  #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
536                              uint32_t bundleFlags = 0;
537                              if (_CFBundleGetObjCImageInfo(bundle, NULL, &bundleFlags) && (bundleFlags & 0x2) == 0) hasRuntimeMismatch = true;
538  #endif
539                          }
540                      }
541  #endif /* BINARY_SUPPORT_DYLD */
542                      if (hasRuntimeMismatch) {
543                          localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableRuntimeMismatchError, debugString);
544                      } else if (!hasSuitableArch) {
545                          localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableArchitectureMismatchError, debugString);
546                      } else {
547                          localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLoadError, debugString);
548                      }
549                      CFRelease(archs);
550                  } else {
551                      localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLoadError, debugString);
552                  }
553                  if (debugString) CFRelease(debugString);
554              }
555          } else {
556              if (error) localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
557          }
558          if (executableURL) CFRelease(executableURL);
559      }
560      if (!retval && error) *error = localError;
561      return retval;
562  }
563  
564  CF_PRIVATE Boolean _CFBundleDlfcnLoadBundle(CFBundleRef bundle, Boolean forceGlobal, CFErrorRef *error) {
565      CFErrorRef localError = NULL, *subError = (error ? &localError : NULL);
566      if (!bundle->_isLoaded) {
567          CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
568          char buff[CFMaxPathSize];
569          if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) {
570              int mode = forceGlobal ? (RTLD_LAZY | RTLD_GLOBAL | RTLD_FIRST) : (RTLD_NOW | RTLD_LOCAL | RTLD_FIRST);
571              void *cookie = dlopen(buff, mode);
572  #if LOG_BUNDLE_LOAD
573              printf("dlfcn load bundle %p, dlopen of %s mode 0x%x returns handle %p\n", bundle, buff, mode, cookie);
574  #endif /* LOG_BUNDLE_LOAD */
575              if (cookie && cookie == bundle->_handleCookie) {
576                  // during the call to dlopen, arbitrary init routines may have run and caused bundle->_handleCookie to be set, in which case proper reference counting requires that reference to be released with dlclose
577  #if LOG_BUNDLE_LOAD
578                  printf("dlfcn load bundle %p closing existing reference to handle %p\n", bundle, cookie);
579  #endif /* LOG_BUNDLE_LOAD */
580                  dlclose(bundle->_handleCookie);
581              }
582              bundle->_handleCookie = cookie;
583              if (bundle->_handleCookie) {
584                  bundle->_isLoaded = true;
585              } else {
586                  const char *dyldError = dlerror();
587                  CFStringRef errorString = dyldError ? CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, dyldError) : NULL;
588                  if (error) {
589                      _CFBundleDlfcnPreflight(bundle, subError);
590                      if (!localError) localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, errorString);
591                  } else {
592                      CFStringRef executableString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, buff);
593                      CFLog(__kCFLogBundle, CFSTR("Error loading %@:  %@"), executableString, errorString ? errorString : CFSTR("(no additional info)"));
594                      if (executableString) CFRelease(executableString);
595                  }
596                  if (errorString) CFRelease(errorString);
597              }
598          } else {
599              if (error) {
600                  localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
601              } else {
602                  CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle);
603              }
604          }
605          if (executableURL) CFRelease(executableURL);
606      }
607      if (!bundle->_isLoaded && error) *error = localError;
608      return bundle->_isLoaded;
609  }
610  
611  CF_PRIVATE Boolean _CFBundleDlfcnLoadFramework(CFBundleRef bundle, CFErrorRef *error) {
612      CFErrorRef localError = NULL, *subError = (error ? &localError : NULL);
613      if (!bundle->_isLoaded) {
614          CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
615          char buff[CFMaxPathSize];
616          if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) {
617              int mode = RTLD_LAZY | RTLD_GLOBAL | RTLD_FIRST;
618              void *cookie = dlopen(buff, mode);
619  #if LOG_BUNDLE_LOAD
620              printf("dlfcn load framework %p, dlopen of %s mode 0x%x returns handle %p\n", bundle, buff, mode, cookie);
621  #endif /* LOG_BUNDLE_LOAD */
622              if (cookie && cookie == bundle->_handleCookie) {
623                  // during the call to dlopen, arbitrary init routines may have run and caused bundle->_handleCookie to be set, in which case proper reference counting requires that reference to be released with dlclose
624  #if LOG_BUNDLE_LOAD
625                  printf("dlfcn load framework %p closing existing reference to handle %p\n", bundle, cookie);
626  #endif /* LOG_BUNDLE_LOAD */
627                  dlclose(bundle->_handleCookie);
628              }
629              bundle->_handleCookie = cookie;
630              if (bundle->_handleCookie) {
631                  bundle->_isLoaded = true;
632              } else {
633                  const char *dyldError = dlerror();
634                  CFStringRef errorString = dyldError ? CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, dyldError) : NULL;
635                  if (error) {
636                      _CFBundleDlfcnPreflight(bundle, subError);
637                      if (!localError) localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, errorString);
638                  } else {
639                      CFStringRef executableString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, buff);
640                      CFLog(__kCFLogBundle, CFSTR("Error loading %@:  %@"), executableString, errorString ? errorString : CFSTR("(no additional info)"));
641                  }
642                  if (errorString) CFRelease(errorString);
643              }
644          } else {
645              if (error) {
646                  localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
647              } else {
648                  CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle);
649              }
650          }
651          if (executableURL) CFRelease(executableURL);
652      }
653      if (!bundle->_isLoaded && error) *error = localError;
654      return bundle->_isLoaded;
655  }
656  
657  CF_PRIVATE void _CFBundleDlfcnUnload(CFBundleRef bundle) {
658      if (bundle->_isLoaded) {
659  #if LOG_BUNDLE_LOAD
660          printf("dlfcn unload bundle %p, handle %p module %p image %p\n", bundle, bundle->_handleCookie, bundle->_moduleCookie, bundle->_imageCookie);
661  #endif /* LOG_BUNDLE_LOAD */
662          if (0 != dlclose(bundle->_handleCookie)) {
663              CFLog(__kCFLogBundle, CFSTR("Internal error unloading bundle %@"), bundle);
664          } else {
665              bundle->_connectionCookie = bundle->_handleCookie = NULL;
666              bundle->_imageCookie = bundle->_moduleCookie = NULL;
667              bundle->_isLoaded = false;
668          }
669      }
670  }
671  
672  CF_PRIVATE void *_CFBundleDlfcnGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName) {
673      return _CFBundleDlfcnGetSymbolByNameWithSearch(bundle, symbolName, false);
674  }
675  
676  static void *_CFBundleDlfcnGetSymbolByNameWithSearch(CFBundleRef bundle, CFStringRef symbolName, Boolean globalSearch) {
677      void *result = NULL;
678      char buff[1026];
679      
680      if (CFStringGetCString(symbolName, buff, 1024, kCFStringEncodingUTF8)) {
681          result = dlsym(bundle->_handleCookie, buff);
682          if (!result && globalSearch) result = dlsym(RTLD_DEFAULT, buff);
683  #if defined(DEBUG)
684          if (!result) CFLog(__kCFLogBundle, CFSTR("dlsym cannot find symbol %@ in %@"), symbolName, bundle);
685  #endif /* DEBUG */
686  #if LOG_BUNDLE_LOAD
687          printf("bundle %p handle %p module %p image %p dlsym returns symbol %p for %s\n", bundle, bundle->_handleCookie, bundle->_moduleCookie, bundle->_imageCookie, result, buff);
688  #endif /* LOG_BUNDLE_LOAD */
689      }
690      return result;
691  }
692  
693  #if !defined(BINARY_SUPPORT_DYLD)
694  
695  static CFStringRef _CFBundleDlfcnCopyLoadedImagePathForPointer(void *p) {
696      CFStringRef result = NULL;
697      Dl_info info;
698      if (0 != dladdr(p, &info) && info.dli_fname) result = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, info.dli_fname);
699  #if LOG_BUNDLE_LOAD
700      printf("dlfcn image path for pointer %p is %p\n", p, result);
701  #endif /* LOG_BUNDLE_LOAD */
702      return result;
703  }
704  
705  #endif /* !BINARY_SUPPORT_DYLD */
706  #endif /* BINARY_SUPPORT_DLFCN */
707  
708  #if defined(BINARY_SUPPORT_DLL)
709  
710  CF_PRIVATE Boolean _CFBundleDLLLoad(CFBundleRef bundle, CFErrorRef *error) {
711      CFErrorRef localError = NULL;
712      if (!bundle->_isLoaded) {
713          CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
714          wchar_t buff[CFMaxPathSize];
715  
716          if (executableURL && _CFURLGetWideFileSystemRepresentation(executableURL, true, (wchar_t *)buff, CFMaxPathSize)) {
717              bundle->_hModule = LoadLibraryW(buff);
718              if (bundle->_hModule) {
719                  bundle->_isLoaded = true;
720              } else {
721                  if (error) {
722                      localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError);
723                  } else {
724                      CFLog(__kCFLogBundle, CFSTR("Failed to load bundle %@"), bundle);
725                  }
726              }
727          } else {
728              if (error) {
729                  localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
730              } else {
731                  CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle);
732              }
733          }
734          if (executableURL) CFRelease(executableURL);
735      }
736      if (!bundle->_isLoaded && error) *error = localError;
737      return bundle->_isLoaded;
738  }
739  
740  CF_PRIVATE void _CFBundleDLLUnload(CFBundleRef bundle) {
741      if (bundle->_isLoaded) {
742         FreeLibrary(bundle->_hModule);
743         bundle->_hModule = NULL;
744         bundle->_isLoaded = false;
745      }
746  }
747  
748  CF_PRIVATE void *_CFBundleDLLGetSymbolByName(CFBundleRef bundle, CFStringRef symbolName) {
749      void *result = NULL;
750      char buff[1024];
751      if (CFStringGetCString(symbolName, buff, 1024, kCFStringEncodingWindowsLatin1)) result = GetProcAddress(bundle->_hModule, buff);
752      return result;
753  }
754  
755  #endif /* BINARY_SUPPORT_DLL */
756  
757  CF_PRIVATE CFStringRef _CFBundleCopyLoadedImagePathForPointer(void *p) {
758      CFStringRef imagePath = NULL;
759  #if defined(BINARY_SUPPORT_DYLD)
760      if (!imagePath) imagePath = _CFBundleDYLDCopyLoadedImagePathForPointer(p);
761  #elif defined(BINARY_SUPPORT_DLFCN)
762      if (!imagePath) imagePath = _CFBundleDlfcnCopyLoadedImagePathForPointer(p);
763  #endif /* BINARY_SUPPORT_DYLD */
764      return imagePath;
765  }
766  
767  void *CFBundleGetFunctionPointerForName(CFBundleRef bundle, CFStringRef funcName) {
768      void *tvp = NULL;
769      // Load if necessary
770      if (!bundle->_isLoaded) {
771          if (!CFBundleLoadExecutable(bundle)) return NULL;
772      }
773      
774      switch (bundle->_binaryType) {
775  #if defined(BINARY_SUPPORT_DYLD)
776          case __CFBundleDYLDBundleBinary:
777          case __CFBundleDYLDFrameworkBinary:
778          case __CFBundleDYLDExecutableBinary:
779  #if defined(BINARY_SUPPORT_DLFCN)
780              if (bundle->_handleCookie) return _CFBundleDlfcnGetSymbolByName(bundle, funcName);
781  #else /* BINARY_SUPPORT_DLFCN */
782              return _CFBundleDYLDGetSymbolByName(bundle, funcName);
783  #endif /* BINARY_SUPPORT_DLFCN */
784              break;
785  #endif /* BINARY_SUPPORT_DYLD */
786  #if defined(BINARY_SUPPORT_DLL)
787          case __CFBundleDLLBinary:
788              tvp = _CFBundleDLLGetSymbolByName(bundle, funcName);
789              break;
790  #endif /* BINARY_SUPPORT_DLL */
791          default:
792  #if defined(BINARY_SUPPORT_DLFCN)
793              if (bundle->_handleCookie) return _CFBundleDlfcnGetSymbolByName(bundle, funcName);
794  #endif /* BINARY_SUPPORT_DLFCN */
795              break;
796      }
797      return tvp;
798  }
799  
800  void *_CFBundleGetCFMFunctionPointerForName(CFBundleRef bundle, CFStringRef funcName) {
801      void *fp = NULL;
802      // Load if necessary
803      if (!bundle->_isLoaded) {
804          if (!CFBundleLoadExecutable(bundle)) return NULL;
805      }
806  #if defined (BINARY_SUPPORT_DYLD) || defined (BINARY_SUPPORT_DLFCN)
807      switch (bundle->_binaryType) {
808  #if defined(BINARY_SUPPORT_DYLD)
809          case __CFBundleDYLDBundleBinary:
810          case __CFBundleDYLDFrameworkBinary:
811          case __CFBundleDYLDExecutableBinary:
812  #if defined(BINARY_SUPPORT_DLFCN)
813              if (bundle->_handleCookie) fp = _CFBundleDlfcnGetSymbolByNameWithSearch(bundle, funcName, true);
814  #else /* BINARY_SUPPORT_DLFCN */
815              fp = _CFBundleDYLDGetSymbolByNameWithSearch(bundle, funcName, true);
816  #endif /* BINARY_SUPPORT_DLFCN */
817              break;
818  #endif /* BINARY_SUPPORT_DYLD */
819          default:
820  #if defined(BINARY_SUPPORT_DLFCN)
821              if (bundle->_handleCookie) fp = _CFBundleDlfcnGetSymbolByNameWithSearch(bundle, funcName, true);
822  #endif /* BINARY_SUPPORT_DLFCN */
823              break;
824      }
825  #endif /* BINARY_SUPPORT_DYLD || BINARY_SUPPORT_DLFCN */
826      return fp;
827  }
828  
829  void CFBundleGetFunctionPointersForNames(CFBundleRef bundle, CFArrayRef functionNames, void *ftbl[]) {
830      SInt32 i, c;
831      
832      if (!ftbl) return;
833      
834      c = CFArrayGetCount(functionNames);
835      for (i = 0; i < c; i++) ftbl[i] = CFBundleGetFunctionPointerForName(bundle, (CFStringRef)CFArrayGetValueAtIndex(functionNames, i));
836  }
837  
838  void _CFBundleGetCFMFunctionPointersForNames(CFBundleRef bundle, CFArrayRef functionNames, void *ftbl[]) {
839      SInt32 i, c;
840      
841      if (!ftbl) return;
842      
843      c = CFArrayGetCount(functionNames);
844      for (i = 0; i < c; i++) ftbl[i] = _CFBundleGetCFMFunctionPointerForName(bundle, (CFStringRef)CFArrayGetValueAtIndex(functionNames, i));
845  }
846  
847  void *CFBundleGetDataPointerForName(CFBundleRef bundle, CFStringRef symbolName) {
848      void *dp = NULL;
849      // Load if necessary
850      if (!bundle->_isLoaded && !CFBundleLoadExecutable(bundle)) return NULL;
851      
852      switch (bundle->_binaryType) {
853  #if defined(BINARY_SUPPORT_DYLD)
854          case __CFBundleDYLDBundleBinary:
855          case __CFBundleDYLDFrameworkBinary:
856          case __CFBundleDYLDExecutableBinary:
857  #if defined(BINARY_SUPPORT_DLFCN)
858              if (bundle->_handleCookie) dp = _CFBundleDlfcnGetSymbolByName(bundle, symbolName);
859  #else /* BINARY_SUPPORT_DLFCN */
860              dp = _CFBundleDYLDGetSymbolByName(bundle, symbolName);
861  #endif /* BINARY_SUPPORT_DLFCN */
862              break;
863  #endif /* BINARY_SUPPORT_DYLD */
864  #if defined(BINARY_SUPPORT_DLL)
865          case __CFBundleDLLBinary:
866              /* MF:!!! Handle this someday */
867              break;
868  #endif /* BINARY_SUPPORT_DLL */
869          default:
870  #if defined(BINARY_SUPPORT_DLFCN)
871              if (bundle->_handleCookie) dp = _CFBundleDlfcnGetSymbolByName(bundle, symbolName);
872  #endif /* BINARY_SUPPORT_DLFCN */
873              break;
874      }
875      return dp;
876  }
877  
878  void CFBundleGetDataPointersForNames(CFBundleRef bundle, CFArrayRef symbolNames, void *stbl[]) {
879      SInt32 i, c;
880      
881      if (!stbl) return;
882      
883      c = CFArrayGetCount(symbolNames);
884      for (i = 0; i < c; i++) stbl[i] = CFBundleGetDataPointerForName(bundle, (CFStringRef)CFArrayGetValueAtIndex(symbolNames, i));
885  }
886