diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | tests/load.test | 17 | ||||
-rw-r--r-- | unix/tclLoadDyld.c | 543 |
3 files changed, 389 insertions, 178 deletions
@@ -1,3 +1,10 @@ +2007-08-14 Daniel Steffen <das@users.sourceforge.net> + + * unix/tclLoadDyld.c: use dlfcn API on Mac OS X 10.4 and later; fix + issues with loading from memory on intel and 64bit; add debug messages. + + * tests/load.test: add test load-10.1 for loading from vfs. + 2007-08-07 Daniel Steffen <das@users.sourceforge.net> * generic/tclEnv.c: improve environ handling on Mac OS X (adapted diff --git a/tests/load.test b/tests/load.test index 9fe26ab..3824d67 100644 --- a/tests/load.test +++ b/tests/load.test @@ -10,7 +10,7 @@ # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# RCS: @(#) $Id: load.test,v 1.11.2.1 2004/09/14 17:02:56 das Exp $ +# RCS: @(#) $Id: load.test,v 1.11.2.2 2007/08/14 06:34:13 das Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest 2 @@ -44,7 +44,12 @@ set alreadyTotalLoaded [info loaded] # Certain tests require the 'teststaticpkg' command from tcltest ::tcltest::testConstraint teststaticpkg \ - [string compare {} [info commands teststaticpkg]] + [string compare {} [info commands teststaticpkg]] + +# Test load-10.1 requires the 'testsimplefilesystem' command from tcltest + +::tcltest::testConstraint testsimplefilesystem \ + [string compare {} [info commands testsimplefilesystem]] test load-1.1 {basic errors} {} { @@ -201,7 +206,13 @@ test load-9.1 {Tcl_StaticPackage, load already-loaded package into another inter -result {{{{} Loadninepointone} {{} Tcltest}} {{{} Loadninepointone} {{} Tcltest}}} \ -cleanup { interp delete child1 ; interp delete child2 } - +test load-10.1 {load from vfs} \ + -constraints [list $dll $loaded testsimplefilesystem] \ + -setup {set dir [pwd]; cd $testDir; testsimplefilesystem 1} \ + -body {list [catch {load simplefs:/pkgd$ext pkgd} msg] $msg} \ + -result {0 {}} \ + -cleanup {testsimplefilesystem 0; cd $dir; unset dir} + # cleanup ::tcltest::cleanupTests return diff --git a/unix/tclLoadDyld.c b/unix/tclLoadDyld.c index a206019..25bd436 100644 --- a/unix/tclLoadDyld.c +++ b/unix/tclLoadDyld.c @@ -3,7 +3,7 @@ * * This procedure provides a version of the TclLoadFile that works with * Apple's dyld dynamic loading. - * Original version of his file (now superseded long ago) provided by + * Original version of his file (superseded long ago) provided by * Wilfredo Sanchez (wsanchez@apple.com). * * Copyright (c) 1995 Apple Computer, Inc. @@ -12,11 +12,51 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclLoadDyld.c,v 1.14.2.9 2007/04/29 02:20:16 das Exp $ + * RCS: @(#) $Id: tclLoadDyld.c,v 1.14.2.10 2007/08/14 06:34:13 das Exp $ */ #include "tclInt.h" #include "tclPort.h" + +#ifndef MODULE_SCOPE +#define MODULE_SCOPE extern +#endif + +#ifndef TCL_DYLD_USE_DLFCN +/* + * Use preferred dlfcn API on 10.4 and later + */ +# if !defined(NO_DLFCN_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 +# define TCL_DYLD_USE_DLFCN 1 +# else +# define TCL_DYLD_USE_DLFCN 0 +# endif +#endif +#ifndef TCL_DYLD_USE_NSMODULE +/* + * Use deprecated NSModule API only to support 10.3 and earlier: + */ +# if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 +# define TCL_DYLD_USE_NSMODULE 1 +# else +# define TCL_DYLD_USE_NSMODULE 0 +# endif +#endif + +#if TCL_DYLD_USE_DLFCN +#include <dlfcn.h> +#if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1040 +/* + * Support for weakly importing dlfcn API. + */ +extern void *dlopen(const char *path, int mode) WEAK_IMPORT_ATTRIBUTE; +extern void *dlsym(void *handle, const char *symbol) WEAK_IMPORT_ATTRIBUTE; +extern int dlclose(void *handle) WEAK_IMPORT_ATTRIBUTE; +extern char *dlerror(void) WEAK_IMPORT_ATTRIBUTE; +#endif +#endif + +#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY) #include <mach-o/dyld.h> #include <mach-o/fat.h> #include <mach-o/swap.h> @@ -25,24 +65,37 @@ #undef panic #include <mach/mach.h> -#ifndef MODULE_SCOPE -#define MODULE_SCOPE extern -#endif - typedef struct Tcl_DyldModuleHandle { struct Tcl_DyldModuleHandle *nextPtr; NSModule module; } Tcl_DyldModuleHandle; +#endif /* TCL_DYLD_USE_NSMODULE */ typedef struct Tcl_DyldLoadHandle { - CONST struct mach_header *dyldLibHeader; +#if TCL_DYLD_USE_DLFCN + void *dlHandle; +#endif +#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY) + const struct mach_header *dyldLibHeader; Tcl_DyldModuleHandle *modulePtr; +#endif } Tcl_DyldLoadHandle; -#ifdef TCL_LOAD_FROM_MEMORY +#if (TCL_DYLD_USE_DLFCN && MAC_OS_X_VERSION_MIN_REQUIRED < 1040) || \ + defined(TCL_LOAD_FROM_MEMORY) MODULE_SCOPE long tclMacOSXDarwinRelease; #endif + +#ifdef TCL_DEBUG_LOAD +#define TclLoadDbgMsg(m, ...) do { \ + fprintf(stderr, "%s:%d: %s(): " m ".\n", \ + strrchr(__FILE__, '/')+1, __LINE__, __func__, ##__VA_ARGS__); \ + } while (0) +#else +#define TclLoadDbgMsg(m, ...) +#endif +#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY) /* *---------------------------------------------------------------------- * @@ -81,6 +134,7 @@ DyldOFIErrorMsg( return "unknown error"; } } +#endif /* TCL_DYLD_USE_NSMODULE */ /* *---------------------------------------------------------------------- @@ -105,7 +159,7 @@ TclpDlopen( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Obj *pathPtr, /* Name of the file containing the desired * code (UTF-8). */ - Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded + Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded * file which will be passed back to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr) @@ -114,10 +168,23 @@ TclpDlopen( * file. */ { Tcl_DyldLoadHandle *dyldLoadHandle; - CONST struct mach_header *dyldLibHeader; - NSObjectFileImage dyldObjFileImage = NULL; +#if TCL_DYLD_USE_DLFCN + void *dlHandle = NULL; +#endif +#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY) + const struct mach_header *dyldLibHeader = NULL; Tcl_DyldModuleHandle *modulePtr = NULL; - CONST char *native; +#endif +#if TCL_DYLD_USE_NSMODULE + NSLinkEditErrors editError; + int errorNumber; + const char *errorName, *objFileImageErrMsg = NULL; +#endif + const char *errMsg = NULL; + int result; + Tcl_DString ds; + char *fileName = NULL; + const char *nativePath, *nativeFileName = NULL; /* * First try the full path the user gave us. This is particularly @@ -125,92 +192,139 @@ TclpDlopen( * relative path. */ - native = Tcl_FSGetNativePath(pathPtr); - dyldLibHeader = NSAddImage(native, NSADDIMAGE_OPTION_RETURN_ON_ERROR); + nativePath = Tcl_FSGetNativePath(pathPtr); - if (!dyldLibHeader) { - NSLinkEditErrors editError; - int errorNumber; - CONST char *name, *msg, *objFileImageErrMsg = NULL; - - NSLinkEditError(&editError, &errorNumber, &name, &msg); - - if (editError == NSLinkEditFileAccessError) { - /* - * The requested file was not found. Let the OS loader examine the - * binary search path for whatever string the user gave us which - * hopefully refers to a file on the binary path. - */ - - Tcl_DString ds; - char *fileName = Tcl_GetString(pathPtr); - CONST char *native = - Tcl_UtfToExternalDString(NULL, fileName, -1, &ds); - - dyldLibHeader = NSAddImage(native, NSADDIMAGE_OPTION_WITH_SEARCHING - | NSADDIMAGE_OPTION_RETURN_ON_ERROR); - Tcl_DStringFree(&ds); - if (!dyldLibHeader) { - NSLinkEditError(&editError, &errorNumber, &name, &msg); - } - } else if ((editError == NSLinkEditFileFormatError - && errorNumber == EBADMACHO) - || editError == NSLinkEditOtherError){ +#if TCL_DYLD_USE_DLFCN +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 + if (tclMacOSXDarwinRelease >= 8) +#endif + { + dlHandle = dlopen(nativePath, RTLD_NOW | RTLD_LOCAL); + if (!dlHandle) { /* - * The requested file was found but was not of type MH_DYLIB, - * attempt to load it as a MH_BUNDLE. + * Let the OS loader examine the binary search path for whatever + * string the user gave us which hopefully refers to a file on the + * binary path. */ - NSObjectFileImageReturnCode err = - NSCreateObjectFileImageFromFile(native, &dyldObjFileImage); - objFileImageErrMsg = DyldOFIErrorMsg(err); + fileName = Tcl_GetString(pathPtr); + nativeFileName = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds); + dlHandle = dlopen(nativeFileName, RTLD_NOW | RTLD_LOCAL); } - - if (!dyldLibHeader && !dyldObjFileImage) { - Tcl_AppendResult(interp, msg, NULL); - if (msg && *msg) { - Tcl_AppendResult(interp, "\n", NULL); - } - if (objFileImageErrMsg) { - Tcl_AppendResult(interp, - "NSCreateObjectFileImageFromFile() error: ", - objFileImageErrMsg, NULL); + if (dlHandle) { + TclLoadDbgMsg("dlopen() successful"); + } else { + errMsg = dlerror(); + TclLoadDbgMsg("dlopen() failed: %s", errMsg); + } + } + if (!dlHandle) +#endif /* TCL_DYLD_USE_DLFCN */ + { +#if TCL_DYLD_USE_NSMODULE + dyldLibHeader = NSAddImage(nativePath, + NSADDIMAGE_OPTION_RETURN_ON_ERROR); + if (dyldLibHeader) { + TclLoadDbgMsg("NSAddImage() successful"); + } else { + NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg); + if (editError == NSLinkEditFileAccessError) { + /* + * The requested file was not found. Let the OS loader examine + * the binary search path for whatever string the user gave us + * which hopefully refers to a file on the binary path. + */ + + if (!fileName) { + fileName = Tcl_GetString(pathPtr); + nativeFileName = Tcl_UtfToExternalDString(NULL, fileName, + -1, &ds); + } + dyldLibHeader = NSAddImage(nativeFileName, + NSADDIMAGE_OPTION_WITH_SEARCHING | + NSADDIMAGE_OPTION_RETURN_ON_ERROR); + if (dyldLibHeader) { + TclLoadDbgMsg("NSAddImage() successful"); + } else { + NSLinkEditError(&editError, &errorNumber, &errorName, + &errMsg); + TclLoadDbgMsg("NSAddImage() failed: %s", errMsg); + } + } else if ((editError == NSLinkEditFileFormatError + && errorNumber == EBADMACHO) + || editError == NSLinkEditOtherError){ + NSObjectFileImageReturnCode err; + NSObjectFileImage dyldObjFileImage; + NSModule module; + + /* + * The requested file was found but was not of type MH_DYLIB, + * attempt to load it as a MH_BUNDLE. + */ + + err = NSCreateObjectFileImageFromFile(nativePath, + &dyldObjFileImage); + if (err == NSObjectFileImageSuccess && dyldObjFileImage) { + TclLoadDbgMsg("NSCreateObjectFileImageFromFile() " + "successful"); + module = NSLinkModule(dyldObjFileImage, nativePath, + NSLINKMODULE_OPTION_BINDNOW + | NSLINKMODULE_OPTION_RETURN_ON_ERROR); + NSDestroyObjectFileImage(dyldObjFileImage); + if (module) { + modulePtr = (Tcl_DyldModuleHandle *) + ckalloc(sizeof(Tcl_DyldModuleHandle)); + modulePtr->module = module; + modulePtr->nextPtr = NULL; + TclLoadDbgMsg("NSLinkModule() successful"); + } else { + NSLinkEditError(&editError, &errorNumber, &errorName, + &errMsg); + TclLoadDbgMsg("NSLinkModule() failed: %s", errMsg); + } + } else { + objFileImageErrMsg = DyldOFIErrorMsg(err); + TclLoadDbgMsg("NSCreateObjectFileImageFromFile() failed: " + "%s", objFileImageErrMsg); + } } - return TCL_ERROR; } +#endif /* TCL_DYLD_USE_NSMODULE */ } - - if (dyldObjFileImage) { - NSModule module; - - module = NSLinkModule(dyldObjFileImage, native, - NSLINKMODULE_OPTION_BINDNOW - | NSLINKMODULE_OPTION_RETURN_ON_ERROR); - NSDestroyObjectFileImage(dyldObjFileImage); - - if (!module) { - NSLinkEditErrors editError; - int errorNumber; - CONST char *name, *msg; - - NSLinkEditError(&editError, &errorNumber, &name, &msg); - Tcl_AppendResult(interp, msg, NULL); - return TCL_ERROR; + if (0 +#if TCL_DYLD_USE_DLFCN + || dlHandle +#endif +#if TCL_DYLD_USE_NSMODULE + || dyldLibHeader || modulePtr +#endif + ) { + dyldLoadHandle = (Tcl_DyldLoadHandle *) + ckalloc(sizeof(Tcl_DyldLoadHandle)); +#if TCL_DYLD_USE_DLFCN + dyldLoadHandle->dlHandle = dlHandle; +#endif +#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY) + dyldLoadHandle->dyldLibHeader = dyldLibHeader; + dyldLoadHandle->modulePtr = modulePtr; +#endif + *loadHandle = (Tcl_LoadHandle) dyldLoadHandle; + *unloadProcPtr = &TclpUnloadFile; + result = TCL_OK; + } else { + Tcl_AppendResult(interp, errMsg, NULL); +#if TCL_DYLD_USE_NSMODULE + if (objFileImageErrMsg) { + Tcl_AppendResult(interp, "\nNSCreateObjectFileImageFromFile() " + "error: ", objFileImageErrMsg, NULL); } - - modulePtr = (Tcl_DyldModuleHandle *) - ckalloc(sizeof(Tcl_DyldModuleHandle)); - modulePtr->module = module; - modulePtr->nextPtr = NULL; +#endif + result = TCL_ERROR; } - - dyldLoadHandle = (Tcl_DyldLoadHandle *) - ckalloc(sizeof(Tcl_DyldLoadHandle)); - dyldLoadHandle->dyldLibHeader = dyldLibHeader; - dyldLoadHandle->modulePtr = modulePtr; - *loadHandle = (Tcl_LoadHandle) dyldLoadHandle; - *unloadProcPtr = &TclpUnloadFile; - return TCL_OK; + if(fileName) { + Tcl_DStringFree(&ds); + } + return result; } /* @@ -235,68 +349,97 @@ TclpFindSymbol( Tcl_LoadHandle loadHandle, /* Handle from TclpDlopen. */ CONST char *symbol) /* Symbol name to look up. */ { - NSSymbol nsSymbol; - CONST char *native; - Tcl_DString newName, ds; - Tcl_PackageInitProc *proc = NULL; Tcl_DyldLoadHandle *dyldLoadHandle = (Tcl_DyldLoadHandle *) loadHandle; - - /* - * dyld adds an underscore to the beginning of symbol names. - */ + Tcl_PackageInitProc *proc = NULL; + const char *errMsg = NULL; + Tcl_DString ds; + const char *native; native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds); - Tcl_DStringInit(&newName); - Tcl_DStringAppend(&newName, "_", 1); - native = Tcl_DStringAppend(&newName, native, -1); - - if (dyldLoadHandle->dyldLibHeader) { - nsSymbol = NSLookupSymbolInImage(dyldLoadHandle->dyldLibHeader, native, - NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW | - NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); - if (nsSymbol) { - /* - * Until dyld supports unloading of MY_DYLIB binaries, the - * following is not needed. - */ +#if TCL_DYLD_USE_DLFCN + if (dyldLoadHandle->dlHandle) { + proc = dlsym(dyldLoadHandle->dlHandle, native); + if (proc) { + TclLoadDbgMsg("dlsym() successful"); + } else { + errMsg = dlerror(); + TclLoadDbgMsg("dlsym() failed: %s", errMsg); + } + } else +#endif /* TCL_DYLD_USE_DLFCN */ + { +#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY) + NSSymbol nsSymbol = NULL; + Tcl_DString newName; -#ifdef DYLD_SUPPORTS_DYLIB_UNLOADING - NSModule module = NSModuleForSymbol(nsSymbol); - Tcl_DyldModuleHandle *modulePtr = dyldLoadHandle->modulePtr; + /* + * dyld adds an underscore to the beginning of symbol names. + */ - while (modulePtr != NULL) { - if (module == modulePtr->module) { - break; + Tcl_DStringInit(&newName); + Tcl_DStringAppend(&newName, "_", 1); + native = Tcl_DStringAppend(&newName, native, -1); + if (dyldLoadHandle->dyldLibHeader) { + nsSymbol = NSLookupSymbolInImage(dyldLoadHandle->dyldLibHeader, + native, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW | + NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); + if (nsSymbol) { + TclLoadDbgMsg("NSLookupSymbolInImage() successful"); +#ifdef DYLD_SUPPORTS_DYLIB_UNLOADING + /* + * Until dyld supports unloading of MY_DYLIB binaries, the + * following is not needed. + */ + + NSModule module = NSModuleForSymbol(nsSymbol); + Tcl_DyldModuleHandle *modulePtr = dyldLoadHandle->modulePtr; + + while (modulePtr != NULL) { + if (module == modulePtr->module) { + break; + } + modulePtr = modulePtr->nextPtr; + } + if (modulePtr == NULL) { + modulePtr = (Tcl_DyldModuleHandle *) + ckalloc(sizeof(Tcl_DyldModuleHandle)); + modulePtr->module = module; + modulePtr->nextPtr = dyldLoadHandle->modulePtr; + dyldLoadHandle->modulePtr = modulePtr; } - modulePtr = modulePtr->nextPtr; - } - if (modulePtr == NULL) { - modulePtr = (Tcl_DyldModuleHandle *) - ckalloc(sizeof(Tcl_DyldModuleHandle)); - modulePtr->module = module; - modulePtr->nextPtr = dyldLoadHandle->modulePtr; - dyldLoadHandle->modulePtr = modulePtr; - } #endif /* DYLD_SUPPORTS_DYLIB_UNLOADING */ + } else { + NSLinkEditErrors editError; + int errorNumber; + const char *errorName; - } else { - NSLinkEditErrors editError; - int errorNumber; - CONST char *name, *msg; - - NSLinkEditError(&editError, &errorNumber, &name, &msg); - Tcl_AppendResult(interp, msg, NULL); + NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg); + TclLoadDbgMsg("NSLookupSymbolInImage() failed: %s", errMsg); + } + } else if (dyldLoadHandle->modulePtr) { + nsSymbol = NSLookupSymbolInModule( + dyldLoadHandle->modulePtr->module, native); + if (nsSymbol) { + TclLoadDbgMsg("NSLookupSymbolInModule() successful"); + } else { + TclLoadDbgMsg("NSLookupSymbolInModule() failed"); + } } - } else { - nsSymbol = NSLookupSymbolInModule(dyldLoadHandle->modulePtr->module, - native); - } - if (nsSymbol) { - proc = NSAddressOfSymbol(nsSymbol); + if (nsSymbol) { + proc = NSAddressOfSymbol(nsSymbol); + if (proc) { + TclLoadDbgMsg("NSAddressOfSymbol() successful"); + } else { + TclLoadDbgMsg("NSAddressOfSymbol() failed"); + } + } + Tcl_DStringFree(&newName); +#endif /* TCL_DYLD_USE_NSMODULE */ } - Tcl_DStringFree(&newName); Tcl_DStringFree(&ds); - + if (errMsg) { + Tcl_AppendResult(interp, errMsg, NULL); + } return proc; } @@ -327,16 +470,39 @@ TclpUnloadFile( * that represents the loaded file. */ { Tcl_DyldLoadHandle *dyldLoadHandle = (Tcl_DyldLoadHandle *) loadHandle; - Tcl_DyldModuleHandle *modulePtr = dyldLoadHandle->modulePtr; - while (modulePtr != NULL) { - void *ptr; +#if TCL_DYLD_USE_DLFCN + if (dyldLoadHandle->dlHandle) { + int result; - NSUnLinkModule(modulePtr->module, - NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES); - ptr = modulePtr; - modulePtr = modulePtr->nextPtr; - ckfree(ptr); + result = dlclose(dyldLoadHandle->dlHandle); + if (!result) { + TclLoadDbgMsg("dlclose() successful"); + } else { + TclLoadDbgMsg("dlclose() failed: %s", dlerror()); + } + } else +#endif /* TCL_DYLD_USE_DLFCN */ + { +#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY) + Tcl_DyldModuleHandle *modulePtr = dyldLoadHandle->modulePtr; + + while (modulePtr != NULL) { + void *ptr; + bool result; + + result = NSUnLinkModule(modulePtr->module, + NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES); + if (result) { + TclLoadDbgMsg("NSUnLinkModule() successful"); + } else { + TclLoadDbgMsg("NSUnLinkModule() failed"); + } + ptr = modulePtr; + modulePtr = modulePtr->nextPtr; + ckfree(ptr); + } +#endif /* TCL_DYLD_USE_NSMODULE */ } ckfree((char*) dyldLoadHandle); } @@ -440,7 +606,7 @@ TclpLoadMemory( int codeSize, /* Size of code data read into buffer or -1 if * an error occurred and the buffer should * just be freed. */ - Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded + Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded * file which will be passed back to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr) @@ -452,7 +618,7 @@ TclpLoadMemory( NSObjectFileImage dyldObjFileImage = NULL; Tcl_DyldModuleHandle *modulePtr; NSModule module; - CONST char *objFileImageErrMsg = NULL; + const char *objFileImageErrMsg = NULL; /* * Try to create an object file image that we can load from. @@ -460,64 +626,88 @@ TclpLoadMemory( if (codeSize >= 0) { NSObjectFileImageReturnCode err = NSObjectFileImageSuccess; - CONST struct fat_header *fh = buffer; + const struct fat_header *fh = buffer; uint32_t ms = 0; #ifndef __LP64__ - CONST struct mach_header *mh = NULL; - #define mh_magic OSSwapHostToBigInt32(MH_MAGIC) + const struct mach_header *mh = NULL; #define mh_size sizeof(struct mach_header) + #define mh_magic MH_MAGIC + #define arch_abi 0 #else - CONST struct mach_header_64 *mh = NULL; - #define mh_magic OSSwapHostToBigInt32(MH_MAGIC_64) + const struct mach_header_64 *mh = NULL; #define mh_size sizeof(struct mach_header_64) + #define mh_magic MH_MAGIC_64 + #define arch_abi CPU_ARCH_ABI64 #endif - + if ((size_t) codeSize >= sizeof(struct fat_header) && fh->magic == OSSwapHostToBigInt32(FAT_MAGIC)) { + uint32_t fh_nfat_arch = OSSwapBigToHostInt32(fh->nfat_arch); + /* * Fat binary, try to find mach_header for our architecture */ - uint32_t fh_nfat_arch = OSSwapBigToHostInt32(fh->nfat_arch); - - if ((size_t) codeSize >= sizeof(struct fat_header) + + + TclLoadDbgMsg("Fat binary, %d archs", fh_nfat_arch); + if ((size_t) codeSize >= sizeof(struct fat_header) + fh_nfat_arch * sizeof(struct fat_arch)) { void *fatarchs = (char*)buffer + sizeof(struct fat_header); - CONST NXArchInfo *arch = NXGetLocalArchInfo(); + const NXArchInfo *arch = NXGetLocalArchInfo(); struct fat_arch *fa; - + if (fh->magic != FAT_MAGIC) { swap_fat_arch(fatarchs, fh_nfat_arch, arch->byteorder); } - fa = NXFindBestFatArch(arch->cputype, arch->cpusubtype, - fatarchs, fh_nfat_arch); + fa = NXFindBestFatArch(arch->cputype | arch_abi, + arch->cpusubtype, fatarchs, fh_nfat_arch); if (fa) { + TclLoadDbgMsg("NXFindBestFatArch() successful: " + "local cputype %d subtype %d, " + "fat cputype %d subtype %d", + arch->cputype | arch_abi, arch->cpusubtype, + fa->cputype, fa->cpusubtype); mh = (void*)((char*)buffer + fa->offset); ms = fa->size; } else { + TclLoadDbgMsg("NXFindBestFatArch() failed"); err = NSObjectFileImageInappropriateFile; } if (fh->magic != FAT_MAGIC) { swap_fat_arch(fatarchs, fh_nfat_arch, arch->byteorder); } } else { + TclLoadDbgMsg("Fat binary header failure"); err = NSObjectFileImageInappropriateFile; } } else { /* * Thin binary */ + + TclLoadDbgMsg("Thin binary"); mh = buffer; ms = codeSize; } if (ms && !(ms >= mh_size && mh->magic == mh_magic && - mh->filetype == OSSwapHostToBigInt32(MH_BUNDLE))) { + mh->filetype == MH_BUNDLE)) { + TclLoadDbgMsg("Inappropriate file: magic %x filetype %d", + mh->magic, mh->filetype); err = NSObjectFileImageInappropriateFile; } if (err == NSObjectFileImageSuccess) { err = NSCreateObjectFileImageFromMemory(buffer, codeSize, &dyldObjFileImage); + if (err == NSObjectFileImageSuccess) { + TclLoadDbgMsg("NSCreateObjectFileImageFromMemory() " + "successful"); + } else { + objFileImageErrMsg = DyldOFIErrorMsg(err); + TclLoadDbgMsg("NSCreateObjectFileImageFromMemory() failed: %s", + objFileImageErrMsg); + } + } else { + objFileImageErrMsg = DyldOFIErrorMsg(err); } - objFileImageErrMsg = DyldOFIErrorMsg(err); } /* @@ -528,9 +718,8 @@ TclpLoadMemory( if (dyldObjFileImage == NULL) { vm_deallocate(mach_task_self(), (vm_address_t) buffer, size); if (objFileImageErrMsg != NULL) { - Tcl_AppendResult(interp, - "NSCreateObjectFileImageFromMemory() error: ", - objFileImageErrMsg, NULL); + Tcl_AppendResult(interp, "NSCreateObjectFileImageFromMemory() " + "error: ", objFileImageErrMsg, NULL); } return TCL_ERROR; } @@ -542,14 +731,16 @@ TclpLoadMemory( module = NSLinkModule(dyldObjFileImage, "[Memory Based Bundle]", NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_RETURN_ON_ERROR); NSDestroyObjectFileImage(dyldObjFileImage); - - if (!module) { + if (module) { + TclLoadDbgMsg("NSLinkModule() successful"); + } else { NSLinkEditErrors editError; int errorNumber; - CONST char *name, *msg; + const char *errorName, *errMsg; - NSLinkEditError(&editError, &errorNumber, &name, &msg); - Tcl_AppendResult(interp, msg, NULL); + NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg); + TclLoadDbgMsg("NSLinkModule() failed: %s", errMsg); + Tcl_AppendResult(interp, errMsg, NULL); return TCL_ERROR; } @@ -560,21 +751,23 @@ TclpLoadMemory( modulePtr = (Tcl_DyldModuleHandle *) ckalloc(sizeof(Tcl_DyldModuleHandle)); modulePtr->module = module; modulePtr->nextPtr = NULL; - dyldLoadHandle = (Tcl_DyldLoadHandle *) ckalloc(sizeof(Tcl_DyldLoadHandle)); +#if TCL_DYLD_USE_DLFCN + dyldLoadHandle->dlHandle = NULL; +#endif dyldLoadHandle->dyldLibHeader = NULL; dyldLoadHandle->modulePtr = modulePtr; *loadHandle = (Tcl_LoadHandle) dyldLoadHandle; *unloadProcPtr = &TclpUnloadFile; return TCL_OK; } -#endif +#endif /* TCL_LOAD_FROM_MEMORY */ /* * Local Variables: * mode: c * c-basic-offset: 4 - * fill-column: 78 + * fill-column: 79 * End: */ |