Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/tcl8.5.2/unix/tclLoadDyld.c @ 25

Last change on this file since 25 was 25, checked in by landauf, 16 years ago

added tcl to libs

File size: 21.5 KB
Line 
1/*
2 * tclLoadDyld.c --
3 *
4 *      This procedure provides a version of the TclLoadFile that works with
5 *      Apple's dyld dynamic loading.
6 *      Original version of his file (superseded long ago) provided by
7 *      Wilfredo Sanchez (wsanchez@apple.com).
8 *
9 * Copyright (c) 1995 Apple Computer, Inc.
10 * Copyright (c) 2001-2007 Daniel A. Steffen <das@users.sourceforge.net>
11 *
12 * See the file "license.terms" for information on usage and redistribution of
13 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 *
15 * RCS: @(#) $Id: tclLoadDyld.c,v 1.29 2007/12/13 15:28:42 dgp Exp $
16 */
17
18#include "tclInt.h"
19
20#ifndef MODULE_SCOPE
21#define MODULE_SCOPE extern
22#endif
23
24#ifndef TCL_DYLD_USE_DLFCN
25/*
26 * Use preferred dlfcn API on 10.4 and later
27 */
28#   if !defined(NO_DLFCN_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
29#       define TCL_DYLD_USE_DLFCN 1
30#   else
31#       define TCL_DYLD_USE_DLFCN 0
32#   endif
33#endif
34#ifndef TCL_DYLD_USE_NSMODULE
35/*
36 * Use deprecated NSModule API only to support 10.3 and earlier:
37 */
38#   if MAC_OS_X_VERSION_MIN_REQUIRED < 1040
39#       define TCL_DYLD_USE_NSMODULE 1
40#   else
41#       define TCL_DYLD_USE_NSMODULE 0
42#   endif
43#endif
44
45#if TCL_DYLD_USE_DLFCN
46#include <dlfcn.h>
47#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040
48/*
49 * Support for weakly importing dlfcn API.
50 */
51extern void *dlopen(const char *path, int mode) WEAK_IMPORT_ATTRIBUTE;
52extern void *dlsym(void *handle, const char *symbol) WEAK_IMPORT_ATTRIBUTE;
53extern int dlclose(void *handle) WEAK_IMPORT_ATTRIBUTE;
54extern char *dlerror(void) WEAK_IMPORT_ATTRIBUTE;
55#endif
56#endif
57
58#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
59#include <mach-o/dyld.h>
60#include <mach-o/fat.h>
61#include <mach-o/swap.h>
62#include <mach-o/arch.h>
63#include <libkern/OSByteOrder.h>
64#include <mach/mach.h>
65#include <stdbool.h>
66
67typedef struct Tcl_DyldModuleHandle {
68    struct Tcl_DyldModuleHandle *nextPtr;
69    NSModule module;
70} Tcl_DyldModuleHandle;
71#endif /* TCL_DYLD_USE_NSMODULE */
72
73typedef struct Tcl_DyldLoadHandle {
74#if TCL_DYLD_USE_DLFCN
75    void *dlHandle;
76#endif
77#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
78    const struct mach_header *dyldLibHeader;
79    Tcl_DyldModuleHandle *modulePtr;
80#endif
81} Tcl_DyldLoadHandle;
82
83#if (TCL_DYLD_USE_DLFCN && MAC_OS_X_VERSION_MIN_REQUIRED < 1040) || \
84        defined(TCL_LOAD_FROM_MEMORY)
85MODULE_SCOPE long tclMacOSXDarwinRelease;
86#endif
87
88#ifdef TCL_DEBUG_LOAD
89#define TclLoadDbgMsg(m, ...) do { \
90            fprintf(stderr, "%s:%d: %s(): " m ".\n", \
91            strrchr(__FILE__, '/')+1, __LINE__, __func__, ##__VA_ARGS__); \
92        } while (0)
93#else
94#define TclLoadDbgMsg(m, ...)
95#endif
96
97#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
98/*
99 *----------------------------------------------------------------------
100 *
101 * DyldOFIErrorMsg --
102 *
103 *      Converts a numerical NSObjectFileImage error into an error message
104 *      string.
105 *
106 * Results:
107 *      Error message string.
108 *
109 * Side effects:
110 *      None.
111 *
112 *----------------------------------------------------------------------
113 */
114
115static CONST char*
116DyldOFIErrorMsg(
117    int err)
118{
119    switch(err) {
120    case NSObjectFileImageSuccess:
121        return NULL;
122    case NSObjectFileImageFailure:
123        return "object file setup failure";
124    case NSObjectFileImageInappropriateFile:
125        return "not a Mach-O MH_BUNDLE file";
126    case NSObjectFileImageArch:
127        return "no object for this architecture";
128    case NSObjectFileImageFormat:
129        return "bad object file format";
130    case NSObjectFileImageAccess:
131        return "can't read object file";
132    default:
133        return "unknown error";
134    }
135}
136#endif /* TCL_DYLD_USE_NSMODULE */
137
138/*
139 *----------------------------------------------------------------------
140 *
141 * TclpDlopen --
142 *
143 *      Dynamically loads a binary code file into memory and returns a handle
144 *      to the new code.
145 *
146 * Results:
147 *      A standard Tcl completion code. If an error occurs, an error message
148 *      is left in the interpreter's result.
149 *
150 * Side effects:
151 *      New code suddenly appears in memory.
152 *
153 *----------------------------------------------------------------------
154 */
155
156MODULE_SCOPE int
157TclpDlopen(
158    Tcl_Interp *interp,         /* Used for error reporting. */
159    Tcl_Obj *pathPtr,           /* Name of the file containing the desired
160                                 * code (UTF-8). */
161    Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
162                                 * file which will be passed back to
163                                 * (*unloadProcPtr)() to unload the file. */
164    Tcl_FSUnloadFileProc **unloadProcPtr)
165                                /* Filled with address of Tcl_FSUnloadFileProc
166                                 * function which should be used for this
167                                 * file. */
168{
169    Tcl_DyldLoadHandle *dyldLoadHandle;
170#if TCL_DYLD_USE_DLFCN
171    void *dlHandle = NULL;
172#endif
173#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
174    const struct mach_header *dyldLibHeader = NULL;
175    Tcl_DyldModuleHandle *modulePtr = NULL;
176#endif
177#if TCL_DYLD_USE_NSMODULE
178    NSLinkEditErrors editError;
179    int errorNumber;
180    const char *errorName, *objFileImageErrMsg = NULL;
181#endif
182    const char *errMsg = NULL;
183    int result;
184    Tcl_DString ds;
185    char *fileName = NULL;
186    const char *nativePath, *nativeFileName = NULL;
187
188    /*
189     * First try the full path the user gave us. This is particularly
190     * important if the cwd is inside a vfs, and we are trying to load using a
191     * relative path.
192     */
193
194    nativePath = Tcl_FSGetNativePath(pathPtr);
195
196#if TCL_DYLD_USE_DLFCN
197#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040
198    if (tclMacOSXDarwinRelease >= 8)
199#endif
200    {
201        dlHandle = dlopen(nativePath, RTLD_NOW | RTLD_LOCAL);
202        if (!dlHandle) {
203            /*
204             * Let the OS loader examine the binary search path for whatever
205             * string the user gave us which hopefully refers to a file on the
206             * binary path.
207             */
208
209            fileName = Tcl_GetString(pathPtr);
210            nativeFileName = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
211            dlHandle = dlopen(nativeFileName, RTLD_NOW | RTLD_LOCAL);
212        }
213        if (dlHandle) {
214            TclLoadDbgMsg("dlopen() successful");
215        } else {
216            errMsg = dlerror();
217            TclLoadDbgMsg("dlopen() failed: %s", errMsg);
218        }
219    }
220    if (!dlHandle)
221#endif /* TCL_DYLD_USE_DLFCN */
222    {
223#if TCL_DYLD_USE_NSMODULE
224        dyldLibHeader = NSAddImage(nativePath,
225                NSADDIMAGE_OPTION_RETURN_ON_ERROR);
226        if (dyldLibHeader) {
227            TclLoadDbgMsg("NSAddImage() successful");
228        } else {
229            NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg);
230            if (editError == NSLinkEditFileAccessError) {
231                /*
232                 * The requested file was not found. Let the OS loader examine
233                 * the binary search path for whatever string the user gave us
234                 * which hopefully refers to a file on the binary path.
235                 */
236
237                if (!fileName) {
238                    fileName = Tcl_GetString(pathPtr);
239                    nativeFileName = Tcl_UtfToExternalDString(NULL, fileName,
240                            -1, &ds);
241                }
242                dyldLibHeader = NSAddImage(nativeFileName,
243                        NSADDIMAGE_OPTION_WITH_SEARCHING |
244                        NSADDIMAGE_OPTION_RETURN_ON_ERROR);
245                if (dyldLibHeader) {
246                    TclLoadDbgMsg("NSAddImage() successful");
247                } else {
248                    NSLinkEditError(&editError, &errorNumber, &errorName,
249                            &errMsg);
250                    TclLoadDbgMsg("NSAddImage() failed: %s", errMsg);
251                }
252            } else if ((editError == NSLinkEditFileFormatError
253                    && errorNumber == EBADMACHO)
254                    || editError == NSLinkEditOtherError){
255                NSObjectFileImageReturnCode err;
256                NSObjectFileImage dyldObjFileImage;
257                NSModule module;
258
259                /*
260                 * The requested file was found but was not of type MH_DYLIB,
261                 * attempt to load it as a MH_BUNDLE.
262                 */
263
264                err = NSCreateObjectFileImageFromFile(nativePath,
265                        &dyldObjFileImage);
266                if (err == NSObjectFileImageSuccess && dyldObjFileImage) {
267                    TclLoadDbgMsg("NSCreateObjectFileImageFromFile() "
268                            "successful");
269                    module = NSLinkModule(dyldObjFileImage, nativePath,
270                            NSLINKMODULE_OPTION_BINDNOW
271                            | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
272                    NSDestroyObjectFileImage(dyldObjFileImage);
273                    if (module) {
274                        modulePtr = (Tcl_DyldModuleHandle *)
275                                ckalloc(sizeof(Tcl_DyldModuleHandle));
276                        modulePtr->module = module;
277                        modulePtr->nextPtr = NULL;
278                        TclLoadDbgMsg("NSLinkModule() successful");
279                    } else {
280                        NSLinkEditError(&editError, &errorNumber, &errorName,
281                                &errMsg);
282                        TclLoadDbgMsg("NSLinkModule() failed: %s", errMsg);
283                    }
284                } else {
285                    objFileImageErrMsg = DyldOFIErrorMsg(err);
286                    TclLoadDbgMsg("NSCreateObjectFileImageFromFile() failed: "
287                            "%s", objFileImageErrMsg);
288                }
289            }
290        }
291#endif /* TCL_DYLD_USE_NSMODULE */
292    }
293    if (0
294#if TCL_DYLD_USE_DLFCN
295            || dlHandle
296#endif
297#if TCL_DYLD_USE_NSMODULE
298            || dyldLibHeader || modulePtr
299#endif
300    ) {
301        dyldLoadHandle = (Tcl_DyldLoadHandle *)
302                ckalloc(sizeof(Tcl_DyldLoadHandle));
303#if TCL_DYLD_USE_DLFCN
304        dyldLoadHandle->dlHandle = dlHandle;
305#endif
306#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
307        dyldLoadHandle->dyldLibHeader = dyldLibHeader;
308        dyldLoadHandle->modulePtr = modulePtr;
309#endif
310        *loadHandle = (Tcl_LoadHandle) dyldLoadHandle;
311        *unloadProcPtr = &TclpUnloadFile;
312        result = TCL_OK;
313    } else {
314        Tcl_AppendResult(interp, errMsg, NULL);
315#if TCL_DYLD_USE_NSMODULE
316        if (objFileImageErrMsg) {
317            Tcl_AppendResult(interp, "\nNSCreateObjectFileImageFromFile() "
318                    "error: ", objFileImageErrMsg, NULL);
319        }
320#endif
321        result = TCL_ERROR;
322    }
323    if(fileName) {
324        Tcl_DStringFree(&ds);
325    }
326    return result;
327}
328
329/*
330 *----------------------------------------------------------------------
331 *
332 * TclpFindSymbol --
333 *
334 *      Looks up a symbol, by name, through a handle associated with a
335 *      previously loaded piece of code (shared library).
336 *
337 * Results:
338 *      Returns a pointer to the function associated with 'symbol' if it is
339 *      found. Otherwise returns NULL and may leave an error message in the
340 *      interp's result.
341 *
342 *----------------------------------------------------------------------
343 */
344
345MODULE_SCOPE Tcl_PackageInitProc *
346TclpFindSymbol(
347    Tcl_Interp *interp,         /* For error reporting. */
348    Tcl_LoadHandle loadHandle,  /* Handle from TclpDlopen. */
349    CONST char *symbol)         /* Symbol name to look up. */
350{
351    Tcl_DyldLoadHandle *dyldLoadHandle = (Tcl_DyldLoadHandle *) loadHandle;
352    Tcl_PackageInitProc *proc = NULL;
353    const char *errMsg = NULL;
354    Tcl_DString ds;
355    const char *native;
356
357    native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
358#if TCL_DYLD_USE_DLFCN
359    if (dyldLoadHandle->dlHandle) {
360        proc = dlsym(dyldLoadHandle->dlHandle, native);
361        if (proc) {
362            TclLoadDbgMsg("dlsym() successful");
363        } else {
364            errMsg = dlerror();
365            TclLoadDbgMsg("dlsym() failed: %s", errMsg);
366        }
367    } else
368#endif /* TCL_DYLD_USE_DLFCN */
369    {
370#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
371        NSSymbol nsSymbol = NULL;
372        Tcl_DString newName;
373
374        /*
375         * dyld adds an underscore to the beginning of symbol names.
376         */
377
378        Tcl_DStringInit(&newName);
379        Tcl_DStringAppend(&newName, "_", 1);
380        native = Tcl_DStringAppend(&newName, native, -1);
381        if (dyldLoadHandle->dyldLibHeader) {
382            nsSymbol = NSLookupSymbolInImage(dyldLoadHandle->dyldLibHeader,
383                    native, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW |
384                    NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
385            if (nsSymbol) {
386                TclLoadDbgMsg("NSLookupSymbolInImage() successful");
387#ifdef DYLD_SUPPORTS_DYLIB_UNLOADING
388                /*
389                 * Until dyld supports unloading of MY_DYLIB binaries, the
390                 * following is not needed.
391                 */
392
393                NSModule module = NSModuleForSymbol(nsSymbol);
394                Tcl_DyldModuleHandle *modulePtr = dyldLoadHandle->modulePtr;
395
396                while (modulePtr != NULL) {
397                    if (module == modulePtr->module) {
398                        break;
399                    }
400                    modulePtr = modulePtr->nextPtr;
401                }
402                if (modulePtr == NULL) {
403                    modulePtr = (Tcl_DyldModuleHandle *)
404                            ckalloc(sizeof(Tcl_DyldModuleHandle));
405                    modulePtr->module = module;
406                    modulePtr->nextPtr = dyldLoadHandle->modulePtr;
407                    dyldLoadHandle->modulePtr = modulePtr;
408                }
409#endif /* DYLD_SUPPORTS_DYLIB_UNLOADING */
410            } else {
411                NSLinkEditErrors editError;
412                int errorNumber;
413                const char *errorName;
414
415                NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg);
416                TclLoadDbgMsg("NSLookupSymbolInImage() failed: %s", errMsg);
417            }
418        } else if (dyldLoadHandle->modulePtr) {
419            nsSymbol = NSLookupSymbolInModule(
420                    dyldLoadHandle->modulePtr->module, native);
421            if (nsSymbol) {
422                TclLoadDbgMsg("NSLookupSymbolInModule() successful");
423            } else {
424                TclLoadDbgMsg("NSLookupSymbolInModule() failed");
425            }
426        }
427        if (nsSymbol) {
428            proc = NSAddressOfSymbol(nsSymbol);
429            if (proc) {
430                TclLoadDbgMsg("NSAddressOfSymbol() successful");
431            } else {
432                TclLoadDbgMsg("NSAddressOfSymbol() failed");
433            }
434        }
435        Tcl_DStringFree(&newName);
436#endif /* TCL_DYLD_USE_NSMODULE */
437    }
438    Tcl_DStringFree(&ds);
439    if (errMsg) {
440        Tcl_AppendResult(interp, errMsg, NULL);
441    }
442    return proc;
443}
444
445/*
446 *----------------------------------------------------------------------
447 *
448 * TclpUnloadFile --
449 *
450 *      Unloads a dynamically loaded binary code file from memory. Code
451 *      pointers in the formerly loaded file are no longer valid after calling
452 *      this function.
453 *
454 * Results:
455 *      None.
456 *
457 * Side effects:
458 *      Code dissapears from memory. Note that dyld currently only supports
459 *      unloading of binaries of type MH_BUNDLE loaded with NSLinkModule() in
460 *      TclpDlopen() above.
461 *
462 *----------------------------------------------------------------------
463 */
464
465MODULE_SCOPE void
466TclpUnloadFile(
467    Tcl_LoadHandle loadHandle)  /* loadHandle returned by a previous call to
468                                 * TclpDlopen(). The loadHandle is a token
469                                 * that represents the loaded file. */
470{
471    Tcl_DyldLoadHandle *dyldLoadHandle = (Tcl_DyldLoadHandle *) loadHandle;
472
473#if TCL_DYLD_USE_DLFCN
474    if (dyldLoadHandle->dlHandle) {
475        int result;
476
477        result = dlclose(dyldLoadHandle->dlHandle);
478        if (!result) {
479            TclLoadDbgMsg("dlclose() successful");
480        } else {
481            TclLoadDbgMsg("dlclose() failed: %s", dlerror());
482        }
483    } else
484#endif /* TCL_DYLD_USE_DLFCN */
485    {
486#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
487        Tcl_DyldModuleHandle *modulePtr = dyldLoadHandle->modulePtr;
488
489        while (modulePtr != NULL) {
490            void *ptr;
491            bool result;
492
493            result = NSUnLinkModule(modulePtr->module,
494                    NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);
495            if (result) {
496                TclLoadDbgMsg("NSUnLinkModule() successful");
497            } else {
498                TclLoadDbgMsg("NSUnLinkModule() failed");
499            }
500            ptr = modulePtr;
501            modulePtr = modulePtr->nextPtr;
502            ckfree(ptr);
503        }
504#endif /* TCL_DYLD_USE_NSMODULE */
505    }
506    ckfree((char*) dyldLoadHandle);
507}
508
509/*
510 *----------------------------------------------------------------------
511 *
512 * TclGuessPackageName --
513 *
514 *      If the "load" command is invoked without providing a package name,
515 *      this procedure is invoked to try to figure it out.
516 *
517 * Results:
518 *      Always returns 0 to indicate that we couldn't figure out a package
519 *      name; generic code will then try to guess the package from the file
520 *      name. A return value of 1 would have meant that we figured out the
521 *      package name and put it in bufPtr.
522 *
523 * Side effects:
524 *      None.
525 *
526 *----------------------------------------------------------------------
527 */
528
529int
530TclGuessPackageName(
531    CONST char *fileName,       /* Name of file containing package (already
532                                 * translated to local form if needed). */
533    Tcl_DString *bufPtr)        /* Initialized empty dstring. Append package
534                                 * name to this if possible. */
535{
536    return 0;
537}
538
539#ifdef TCL_LOAD_FROM_MEMORY
540/*
541 *----------------------------------------------------------------------
542 *
543 * TclpLoadMemoryGetBuffer --
544 *
545 *      Allocate a buffer that can be used with TclpLoadMemory() below.
546 *
547 * Results:
548 *      Pointer to allocated buffer or NULL if an error occurs.
549 *
550 * Side effects:
551 *      Buffer is allocated.
552 *
553 *----------------------------------------------------------------------
554 */
555
556MODULE_SCOPE void *
557TclpLoadMemoryGetBuffer(
558    Tcl_Interp *interp,         /* Used for error reporting. */
559    int size)                   /* Size of desired buffer. */
560{
561    void *buffer = NULL;
562
563    /*
564     * NSCreateObjectFileImageFromMemory is available but always fails
565     * prior to Darwin 7.
566     */
567    if (tclMacOSXDarwinRelease >= 7) {
568        /*
569         * We must allocate the buffer using vm_allocate, because
570         * NSCreateObjectFileImageFromMemory will dispose of it using
571         * vm_deallocate.
572         */
573
574        if (vm_allocate(mach_task_self(), (vm_address_t *) &buffer, size, 1)) {
575            buffer = NULL;
576        }
577    }
578    return buffer;
579}
580
581/*
582 *----------------------------------------------------------------------
583 *
584 * TclpLoadMemory --
585 *
586 *      Dynamically loads binary code file from memory and returns a handle to
587 *      the new code.
588 *
589 * Results:
590 *      A standard Tcl completion code. If an error occurs, an error message
591 *      is left in the interpreter's result.
592 *
593 * Side effects:
594 *      New code is loaded from memory.
595 *
596 *----------------------------------------------------------------------
597 */
598
599MODULE_SCOPE int
600TclpLoadMemory(
601    Tcl_Interp *interp,         /* Used for error reporting. */
602    void *buffer,               /* Buffer containing the desired code
603                                 * (allocated with TclpLoadMemoryGetBuffer). */
604    int size,                   /* Allocation size of buffer. */
605    int codeSize,               /* Size of code data read into buffer or -1 if
606                                 * an error occurred and the buffer should
607                                 * just be freed. */
608    Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
609                                 * file which will be passed back to
610                                 * (*unloadProcPtr)() to unload the file. */
611    Tcl_FSUnloadFileProc **unloadProcPtr)
612                                /* Filled with address of Tcl_FSUnloadFileProc
613                                 * function which should be used for this
614                                 * file. */
615{
616    Tcl_DyldLoadHandle *dyldLoadHandle;
617    NSObjectFileImage dyldObjFileImage = NULL;
618    Tcl_DyldModuleHandle *modulePtr;
619    NSModule module;
620    const char *objFileImageErrMsg = NULL;
621
622    /*
623     * Try to create an object file image that we can load from.
624     */
625
626    if (codeSize >= 0) {
627        NSObjectFileImageReturnCode err = NSObjectFileImageSuccess;
628        const struct fat_header *fh = buffer;
629        uint32_t ms = 0;
630#ifndef __LP64__
631        const struct mach_header *mh = NULL;
632        #define mh_size  sizeof(struct mach_header)
633        #define mh_magic MH_MAGIC
634        #define arch_abi 0
635#else
636        const struct mach_header_64 *mh = NULL;
637        #define mh_size  sizeof(struct mach_header_64)
638        #define mh_magic MH_MAGIC_64
639        #define arch_abi CPU_ARCH_ABI64
640#endif
641
642        if ((size_t) codeSize >= sizeof(struct fat_header)
643                && fh->magic == OSSwapHostToBigInt32(FAT_MAGIC)) {
644            uint32_t fh_nfat_arch = OSSwapBigToHostInt32(fh->nfat_arch);
645
646            /*
647             * Fat binary, try to find mach_header for our architecture
648             */
649
650            TclLoadDbgMsg("Fat binary, %d archs", fh_nfat_arch);
651            if ((size_t) codeSize >= sizeof(struct fat_header) +
652                    fh_nfat_arch * sizeof(struct fat_arch)) {
653                void *fatarchs = (char*)buffer + sizeof(struct fat_header);
654                const NXArchInfo *arch = NXGetLocalArchInfo();
655                struct fat_arch *fa;
656
657                if (fh->magic != FAT_MAGIC) {
658                    swap_fat_arch(fatarchs, fh_nfat_arch, arch->byteorder);
659                }
660                fa = NXFindBestFatArch(arch->cputype | arch_abi,
661                        arch->cpusubtype, fatarchs, fh_nfat_arch);
662                if (fa) {
663                    TclLoadDbgMsg("NXFindBestFatArch() successful: "
664                            "local cputype %d subtype %d, "
665                            "fat cputype %d subtype %d",
666                            arch->cputype | arch_abi, arch->cpusubtype,
667                            fa->cputype, fa->cpusubtype);
668                    mh = (void*)((char*)buffer + fa->offset);
669                    ms = fa->size;
670                } else {
671                    TclLoadDbgMsg("NXFindBestFatArch() failed");
672                    err = NSObjectFileImageInappropriateFile;
673                }
674                if (fh->magic != FAT_MAGIC) {
675                    swap_fat_arch(fatarchs, fh_nfat_arch, arch->byteorder);
676                }
677            } else {
678                TclLoadDbgMsg("Fat binary header failure");
679                err = NSObjectFileImageInappropriateFile;
680            }
681        } else {
682            /*
683             * Thin binary
684             */
685
686            TclLoadDbgMsg("Thin binary");
687            mh = buffer;
688            ms = codeSize;
689        }
690        if (ms && !(ms >= mh_size && mh->magic == mh_magic &&
691                 mh->filetype == MH_BUNDLE)) {
692            TclLoadDbgMsg("Inappropriate file: magic %x filetype %d",
693                    mh->magic, mh->filetype);
694            err = NSObjectFileImageInappropriateFile;
695        }
696        if (err == NSObjectFileImageSuccess) {
697            err = NSCreateObjectFileImageFromMemory(buffer, codeSize,
698                    &dyldObjFileImage);
699            if (err == NSObjectFileImageSuccess) {
700                TclLoadDbgMsg("NSCreateObjectFileImageFromMemory() "
701                        "successful");
702            } else {
703                objFileImageErrMsg = DyldOFIErrorMsg(err);
704                TclLoadDbgMsg("NSCreateObjectFileImageFromMemory() failed: %s",
705                        objFileImageErrMsg);
706            }
707        } else {
708            objFileImageErrMsg = DyldOFIErrorMsg(err);
709        }
710    }
711
712    /*
713     * If it went wrong (or we were asked to just deallocate), get rid of the
714     * memory block and create an error message.
715     */
716
717    if (dyldObjFileImage == NULL) {
718        vm_deallocate(mach_task_self(), (vm_address_t) buffer, size);
719        if (objFileImageErrMsg != NULL) {
720            Tcl_AppendResult(interp, "NSCreateObjectFileImageFromMemory() "
721                    "error: ", objFileImageErrMsg, NULL);
722        }
723        return TCL_ERROR;
724    }
725
726    /*
727     * Extract the module we want from the image of the object file.
728     */
729
730    module = NSLinkModule(dyldObjFileImage, "[Memory Based Bundle]",
731            NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
732    NSDestroyObjectFileImage(dyldObjFileImage);
733    if (module) {
734        TclLoadDbgMsg("NSLinkModule() successful");
735    } else {
736        NSLinkEditErrors editError;
737        int errorNumber;
738        const char *errorName, *errMsg;
739
740        NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg);
741        TclLoadDbgMsg("NSLinkModule() failed: %s", errMsg);
742        Tcl_AppendResult(interp, errMsg, NULL);
743        return TCL_ERROR;
744    }
745
746    /*
747     * Stash the module reference within the load handle we create and return.
748     */
749
750    modulePtr = (Tcl_DyldModuleHandle *) ckalloc(sizeof(Tcl_DyldModuleHandle));
751    modulePtr->module = module;
752    modulePtr->nextPtr = NULL;
753    dyldLoadHandle = (Tcl_DyldLoadHandle *)
754            ckalloc(sizeof(Tcl_DyldLoadHandle));
755#if TCL_DYLD_USE_DLFCN
756    dyldLoadHandle->dlHandle = NULL;
757#endif
758    dyldLoadHandle->dyldLibHeader = NULL;
759    dyldLoadHandle->modulePtr = modulePtr;
760    *loadHandle = (Tcl_LoadHandle) dyldLoadHandle;
761    *unloadProcPtr = &TclpUnloadFile;
762    return TCL_OK;
763}
764#endif /* TCL_LOAD_FROM_MEMORY */
765
766/*
767 * Local Variables:
768 * mode: c
769 * c-basic-offset: 4
770 * fill-column: 79
771 * End:
772 */
Note: See TracBrowser for help on using the repository browser.