summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--tests/load.test17
-rw-r--r--unix/tclLoadDyld.c543
3 files changed, 389 insertions, 178 deletions
diff --git a/ChangeLog b/ChangeLog
index 296f312..4b3114a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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:
*/