os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/unix/tclLoadDyld.c
Update contrib.
4 * This procedure provides a version of the TclLoadFile that works with
5 * Apple's dyld dynamic loading.
6 * Original version of his file (now superseded long ago) provided by
7 * Wilfredo Sanchez (wsanchez@apple.com).
9 * Copyright (c) 1995 Apple Computer, Inc.
10 * Copyright (c) 2001-2007 Daniel A. Steffen <das@users.sourceforge.net>
12 * See the file "license.terms" for information on usage and redistribution of
13 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
15 * RCS: @(#) $Id: tclLoadDyld.c,v 1.14.2.9 2007/04/29 02:20:16 das Exp $
20 #include <mach-o/dyld.h>
21 #include <mach-o/fat.h>
22 #include <mach-o/swap.h>
23 #include <mach-o/arch.h>
24 #include <libkern/OSByteOrder.h>
26 #include <mach/mach.h>
29 #define MODULE_SCOPE extern
32 typedef struct Tcl_DyldModuleHandle {
33 struct Tcl_DyldModuleHandle *nextPtr;
35 } Tcl_DyldModuleHandle;
37 typedef struct Tcl_DyldLoadHandle {
38 CONST struct mach_header *dyldLibHeader;
39 Tcl_DyldModuleHandle *modulePtr;
42 #ifdef TCL_LOAD_FROM_MEMORY
43 MODULE_SCOPE long tclMacOSXDarwinRelease;
47 *----------------------------------------------------------------------
51 * Converts a numerical NSObjectFileImage error into an error message
55 * Error message string.
60 *----------------------------------------------------------------------
68 case NSObjectFileImageSuccess:
70 case NSObjectFileImageFailure:
71 return "object file setup failure";
72 case NSObjectFileImageInappropriateFile:
73 return "not a Mach-O MH_BUNDLE file";
74 case NSObjectFileImageArch:
75 return "no object for this architecture";
76 case NSObjectFileImageFormat:
77 return "bad object file format";
78 case NSObjectFileImageAccess:
79 return "can't read object file";
81 return "unknown error";
86 *----------------------------------------------------------------------
90 * Dynamically loads a binary code file into memory and returns a handle
94 * A standard Tcl completion code. If an error occurs, an error message
95 * is left in the interpreter's result.
98 * New code suddenly appears in memory.
100 *----------------------------------------------------------------------
105 Tcl_Interp *interp, /* Used for error reporting. */
106 Tcl_Obj *pathPtr, /* Name of the file containing the desired
108 Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
109 * file which will be passed back to
110 * (*unloadProcPtr)() to unload the file. */
111 Tcl_FSUnloadFileProc **unloadProcPtr)
112 /* Filled with address of Tcl_FSUnloadFileProc
113 * function which should be used for this
116 Tcl_DyldLoadHandle *dyldLoadHandle;
117 CONST struct mach_header *dyldLibHeader;
118 NSObjectFileImage dyldObjFileImage = NULL;
119 Tcl_DyldModuleHandle *modulePtr = NULL;
123 * First try the full path the user gave us. This is particularly
124 * important if the cwd is inside a vfs, and we are trying to load using a
128 native = Tcl_FSGetNativePath(pathPtr);
129 dyldLibHeader = NSAddImage(native, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
131 if (!dyldLibHeader) {
132 NSLinkEditErrors editError;
134 CONST char *name, *msg, *objFileImageErrMsg = NULL;
136 NSLinkEditError(&editError, &errorNumber, &name, &msg);
138 if (editError == NSLinkEditFileAccessError) {
140 * The requested file was not found. Let the OS loader examine the
141 * binary search path for whatever string the user gave us which
142 * hopefully refers to a file on the binary path.
146 char *fileName = Tcl_GetString(pathPtr);
148 Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
150 dyldLibHeader = NSAddImage(native, NSADDIMAGE_OPTION_WITH_SEARCHING
151 | NSADDIMAGE_OPTION_RETURN_ON_ERROR);
152 Tcl_DStringFree(&ds);
153 if (!dyldLibHeader) {
154 NSLinkEditError(&editError, &errorNumber, &name, &msg);
156 } else if ((editError == NSLinkEditFileFormatError
157 && errorNumber == EBADMACHO)
158 || editError == NSLinkEditOtherError){
160 * The requested file was found but was not of type MH_DYLIB,
161 * attempt to load it as a MH_BUNDLE.
164 NSObjectFileImageReturnCode err =
165 NSCreateObjectFileImageFromFile(native, &dyldObjFileImage);
166 objFileImageErrMsg = DyldOFIErrorMsg(err);
169 if (!dyldLibHeader && !dyldObjFileImage) {
170 Tcl_AppendResult(interp, msg, NULL);
172 Tcl_AppendResult(interp, "\n", NULL);
174 if (objFileImageErrMsg) {
175 Tcl_AppendResult(interp,
176 "NSCreateObjectFileImageFromFile() error: ",
177 objFileImageErrMsg, NULL);
183 if (dyldObjFileImage) {
186 module = NSLinkModule(dyldObjFileImage, native,
187 NSLINKMODULE_OPTION_BINDNOW
188 | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
189 NSDestroyObjectFileImage(dyldObjFileImage);
192 NSLinkEditErrors editError;
194 CONST char *name, *msg;
196 NSLinkEditError(&editError, &errorNumber, &name, &msg);
197 Tcl_AppendResult(interp, msg, NULL);
201 modulePtr = (Tcl_DyldModuleHandle *)
202 ckalloc(sizeof(Tcl_DyldModuleHandle));
203 modulePtr->module = module;
204 modulePtr->nextPtr = NULL;
207 dyldLoadHandle = (Tcl_DyldLoadHandle *)
208 ckalloc(sizeof(Tcl_DyldLoadHandle));
209 dyldLoadHandle->dyldLibHeader = dyldLibHeader;
210 dyldLoadHandle->modulePtr = modulePtr;
211 *loadHandle = (Tcl_LoadHandle) dyldLoadHandle;
212 *unloadProcPtr = &TclpUnloadFile;
217 *----------------------------------------------------------------------
221 * Looks up a symbol, by name, through a handle associated with a
222 * previously loaded piece of code (shared library).
225 * Returns a pointer to the function associated with 'symbol' if it is
226 * found. Otherwise returns NULL and may leave an error message in the
229 *----------------------------------------------------------------------
232 MODULE_SCOPE Tcl_PackageInitProc *
234 Tcl_Interp *interp, /* For error reporting. */
235 Tcl_LoadHandle loadHandle, /* Handle from TclpDlopen. */
236 CONST char *symbol) /* Symbol name to look up. */
240 Tcl_DString newName, ds;
241 Tcl_PackageInitProc *proc = NULL;
242 Tcl_DyldLoadHandle *dyldLoadHandle = (Tcl_DyldLoadHandle *) loadHandle;
245 * dyld adds an underscore to the beginning of symbol names.
248 native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
249 Tcl_DStringInit(&newName);
250 Tcl_DStringAppend(&newName, "_", 1);
251 native = Tcl_DStringAppend(&newName, native, -1);
253 if (dyldLoadHandle->dyldLibHeader) {
254 nsSymbol = NSLookupSymbolInImage(dyldLoadHandle->dyldLibHeader, native,
255 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW |
256 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
259 * Until dyld supports unloading of MY_DYLIB binaries, the
260 * following is not needed.
263 #ifdef DYLD_SUPPORTS_DYLIB_UNLOADING
264 NSModule module = NSModuleForSymbol(nsSymbol);
265 Tcl_DyldModuleHandle *modulePtr = dyldLoadHandle->modulePtr;
267 while (modulePtr != NULL) {
268 if (module == modulePtr->module) {
271 modulePtr = modulePtr->nextPtr;
273 if (modulePtr == NULL) {
274 modulePtr = (Tcl_DyldModuleHandle *)
275 ckalloc(sizeof(Tcl_DyldModuleHandle));
276 modulePtr->module = module;
277 modulePtr->nextPtr = dyldLoadHandle->modulePtr;
278 dyldLoadHandle->modulePtr = modulePtr;
280 #endif /* DYLD_SUPPORTS_DYLIB_UNLOADING */
283 NSLinkEditErrors editError;
285 CONST char *name, *msg;
287 NSLinkEditError(&editError, &errorNumber, &name, &msg);
288 Tcl_AppendResult(interp, msg, NULL);
291 nsSymbol = NSLookupSymbolInModule(dyldLoadHandle->modulePtr->module,
295 proc = NSAddressOfSymbol(nsSymbol);
297 Tcl_DStringFree(&newName);
298 Tcl_DStringFree(&ds);
304 *----------------------------------------------------------------------
308 * Unloads a dynamically loaded binary code file from memory. Code
309 * pointers in the formerly loaded file are no longer valid after calling
316 * Code dissapears from memory. Note that dyld currently only supports
317 * unloading of binaries of type MH_BUNDLE loaded with NSLinkModule() in
318 * TclpDlopen() above.
320 *----------------------------------------------------------------------
325 Tcl_LoadHandle loadHandle) /* loadHandle returned by a previous call to
326 * TclpDlopen(). The loadHandle is a token
327 * that represents the loaded file. */
329 Tcl_DyldLoadHandle *dyldLoadHandle = (Tcl_DyldLoadHandle *) loadHandle;
330 Tcl_DyldModuleHandle *modulePtr = dyldLoadHandle->modulePtr;
332 while (modulePtr != NULL) {
335 NSUnLinkModule(modulePtr->module,
336 NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);
338 modulePtr = modulePtr->nextPtr;
341 ckfree((char*) dyldLoadHandle);
345 *----------------------------------------------------------------------
347 * TclGuessPackageName --
349 * If the "load" command is invoked without providing a package name,
350 * this procedure is invoked to try to figure it out.
353 * Always returns 0 to indicate that we couldn't figure out a package
354 * name; generic code will then try to guess the package from the file
355 * name. A return value of 1 would have meant that we figured out the
356 * package name and put it in bufPtr.
361 *----------------------------------------------------------------------
366 CONST char *fileName, /* Name of file containing package (already
367 * translated to local form if needed). */
368 Tcl_DString *bufPtr) /* Initialized empty dstring. Append package
369 * name to this if possible. */
374 #ifdef TCL_LOAD_FROM_MEMORY
376 *----------------------------------------------------------------------
378 * TclpLoadMemoryGetBuffer --
380 * Allocate a buffer that can be used with TclpLoadMemory() below.
383 * Pointer to allocated buffer or NULL if an error occurs.
386 * Buffer is allocated.
388 *----------------------------------------------------------------------
392 TclpLoadMemoryGetBuffer(
393 Tcl_Interp *interp, /* Used for error reporting. */
394 int size) /* Size of desired buffer. */
399 * NSCreateObjectFileImageFromMemory is available but always fails
402 if (tclMacOSXDarwinRelease >= 7) {
404 * We must allocate the buffer using vm_allocate, because
405 * NSCreateObjectFileImageFromMemory will dispose of it using
409 if (vm_allocate(mach_task_self(), (vm_address_t *) &buffer, size, 1)) {
417 *----------------------------------------------------------------------
421 * Dynamically loads binary code file from memory and returns a handle to
425 * A standard Tcl completion code. If an error occurs, an error message
426 * is left in the interpreter's result.
429 * New code is loaded from memory.
431 *----------------------------------------------------------------------
436 Tcl_Interp *interp, /* Used for error reporting. */
437 void *buffer, /* Buffer containing the desired code
438 * (allocated with TclpLoadMemoryGetBuffer). */
439 int size, /* Allocation size of buffer. */
440 int codeSize, /* Size of code data read into buffer or -1 if
441 * an error occurred and the buffer should
443 Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
444 * file which will be passed back to
445 * (*unloadProcPtr)() to unload the file. */
446 Tcl_FSUnloadFileProc **unloadProcPtr)
447 /* Filled with address of Tcl_FSUnloadFileProc
448 * function which should be used for this
451 Tcl_DyldLoadHandle *dyldLoadHandle;
452 NSObjectFileImage dyldObjFileImage = NULL;
453 Tcl_DyldModuleHandle *modulePtr;
455 CONST char *objFileImageErrMsg = NULL;
458 * Try to create an object file image that we can load from.
462 NSObjectFileImageReturnCode err = NSObjectFileImageSuccess;
463 CONST struct fat_header *fh = buffer;
466 CONST struct mach_header *mh = NULL;
467 #define mh_magic OSSwapHostToBigInt32(MH_MAGIC)
468 #define mh_size sizeof(struct mach_header)
470 CONST struct mach_header_64 *mh = NULL;
471 #define mh_magic OSSwapHostToBigInt32(MH_MAGIC_64)
472 #define mh_size sizeof(struct mach_header_64)
475 if ((size_t) codeSize >= sizeof(struct fat_header)
476 && fh->magic == OSSwapHostToBigInt32(FAT_MAGIC)) {
478 * Fat binary, try to find mach_header for our architecture
480 uint32_t fh_nfat_arch = OSSwapBigToHostInt32(fh->nfat_arch);
482 if ((size_t) codeSize >= sizeof(struct fat_header) +
483 fh_nfat_arch * sizeof(struct fat_arch)) {
484 void *fatarchs = (char*)buffer + sizeof(struct fat_header);
485 CONST NXArchInfo *arch = NXGetLocalArchInfo();
488 if (fh->magic != FAT_MAGIC) {
489 swap_fat_arch(fatarchs, fh_nfat_arch, arch->byteorder);
491 fa = NXFindBestFatArch(arch->cputype, arch->cpusubtype,
492 fatarchs, fh_nfat_arch);
494 mh = (void*)((char*)buffer + fa->offset);
497 err = NSObjectFileImageInappropriateFile;
499 if (fh->magic != FAT_MAGIC) {
500 swap_fat_arch(fatarchs, fh_nfat_arch, arch->byteorder);
503 err = NSObjectFileImageInappropriateFile;
512 if (ms && !(ms >= mh_size && mh->magic == mh_magic &&
513 mh->filetype == OSSwapHostToBigInt32(MH_BUNDLE))) {
514 err = NSObjectFileImageInappropriateFile;
516 if (err == NSObjectFileImageSuccess) {
517 err = NSCreateObjectFileImageFromMemory(buffer, codeSize,
520 objFileImageErrMsg = DyldOFIErrorMsg(err);
524 * If it went wrong (or we were asked to just deallocate), get rid of the
525 * memory block and create an error message.
528 if (dyldObjFileImage == NULL) {
529 vm_deallocate(mach_task_self(), (vm_address_t) buffer, size);
530 if (objFileImageErrMsg != NULL) {
531 Tcl_AppendResult(interp,
532 "NSCreateObjectFileImageFromMemory() error: ",
533 objFileImageErrMsg, NULL);
539 * Extract the module we want from the image of the object file.
542 module = NSLinkModule(dyldObjFileImage, "[Memory Based Bundle]",
543 NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
544 NSDestroyObjectFileImage(dyldObjFileImage);
547 NSLinkEditErrors editError;
549 CONST char *name, *msg;
551 NSLinkEditError(&editError, &errorNumber, &name, &msg);
552 Tcl_AppendResult(interp, msg, NULL);
557 * Stash the module reference within the load handle we create and return.
560 modulePtr = (Tcl_DyldModuleHandle *) ckalloc(sizeof(Tcl_DyldModuleHandle));
561 modulePtr->module = module;
562 modulePtr->nextPtr = NULL;
564 dyldLoadHandle = (Tcl_DyldLoadHandle *)
565 ckalloc(sizeof(Tcl_DyldLoadHandle));
566 dyldLoadHandle->dyldLibHeader = NULL;
567 dyldLoadHandle->modulePtr = modulePtr;
568 *loadHandle = (Tcl_LoadHandle) dyldLoadHandle;
569 *unloadProcPtr = &TclpUnloadFile;