summaryrefslogtreecommitdiffstats
path: root/unix/tclLoadDyld.c
diff options
context:
space:
mode:
authordas <das>2005-07-30 07:58:11 (GMT)
committerdas <das>2005-07-30 07:58:11 (GMT)
commitc918210ee55ae018cc40f8a8b411feed5af07de4 (patch)
treee9aa2445feb4a2bd335c814c030d801a960eebdb /unix/tclLoadDyld.c
parent34c1b26fda7971d730ebcf6498ef36793dc84609 (diff)
downloadtcl-c918210ee55ae018cc40f8a8b411feed5af07de4.zip
tcl-c918210ee55ae018cc40f8a8b411feed5af07de4.tar.gz
tcl-c918210ee55ae018cc40f8a8b411feed5af07de4.tar.bz2
* unix/configure, unix/tcl.m4: revert 2005-07-28 change.
* unix/tclLoadDyld.c (TclpDlopen, TclpLoadMemory): workarounds for bugs/changes in behaviour in Mac OS X 10.4 Tiger, sync formatting changes from HEAD.
Diffstat (limited to 'unix/tclLoadDyld.c')
-rw-r--r--unix/tclLoadDyld.c594
1 files changed, 331 insertions, 263 deletions
diff --git a/unix/tclLoadDyld.c b/unix/tclLoadDyld.c
index 10afad7..1796307 100644
--- a/unix/tclLoadDyld.c
+++ b/unix/tclLoadDyld.c
@@ -1,17 +1,18 @@
-/*
+/*
* tclLoadDyld.c --
*
- * This procedure provides a version of the TclLoadFile that
- * works with Apple's dyld dynamic loading. This file
- * provided by Wilfredo Sanchez (wsanchez@apple.com).
- * This works on Mac OS X.
+ * 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
+ * Wilfredo Sanchez (wsanchez@apple.com).
*
* Copyright (c) 1995 Apple Computer, Inc.
+ * Copyright (c) 2005 Daniel A. Steffen <das@users.sourceforge.net>
*
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ * 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.3 2005/06/04 07:05:14 das Exp $
+ * RCS: @(#) $Id: tclLoadDyld.c,v 1.14.2.4 2005/07/30 07:58:16 das Exp $
*/
#include "tclInt.h"
@@ -21,18 +22,18 @@
#include <mach/mach.h>
typedef struct Tcl_DyldModuleHandle {
- struct Tcl_DyldModuleHandle *nextModuleHandle;
+ struct Tcl_DyldModuleHandle *nextPtr;
NSModule module;
} Tcl_DyldModuleHandle;
typedef struct Tcl_DyldLoadHandle {
- CONST struct mach_header *dyld_lib;
- Tcl_DyldModuleHandle *firstModuleHandle;
+ CONST struct mach_header *dyldLibHeader;
+ Tcl_DyldModuleHandle *modulePtr;
} Tcl_DyldLoadHandle;
#ifdef TCL_LOAD_FROM_MEMORY
typedef struct ThreadSpecificData {
- int haveLoadMemory;
+ int haveLoadMemory;
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
@@ -43,44 +44,36 @@ static Tcl_ThreadDataKey dataKey;
*
* DyldOFIErrorMsg --
*
- * Converts a numerical NSObjectFileImage error into an
- * error message string.
+ * Converts a numerical NSObjectFileImage error into an error message
+ * string.
*
* Results:
- * Error message string.
+ * Error message string.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
-static CONST char* DyldOFIErrorMsg(int err) {
- CONST char *ofi_msg = NULL;
-
- if (err != NSObjectFileImageSuccess) {
- switch(err) {
- case NSObjectFileImageFailure:
- ofi_msg = "object file setup failure";
- break;
- case NSObjectFileImageInappropriateFile:
- ofi_msg = "not a Mach-O MH_BUNDLE file";
- break;
- case NSObjectFileImageArch:
- ofi_msg = "no object for this architecture";
- break;
- case NSObjectFileImageFormat:
- ofi_msg = "bad object file format";
- break;
- case NSObjectFileImageAccess:
- ofi_msg = "can't read object file";
- break;
- default:
- ofi_msg = "unknown error";
- break;
- }
+static CONST char*
+DyldOFIErrorMsg(int err) {
+ switch(err) {
+ case NSObjectFileImageSuccess:
+ return NULL;
+ case NSObjectFileImageFailure:
+ return "object file setup failure";
+ case NSObjectFileImageInappropriateFile:
+ return "not a Mach-O MH_BUNDLE file";
+ case NSObjectFileImageArch:
+ return "no object for this architecture";
+ case NSObjectFileImageFormat:
+ return "bad object file format";
+ case NSObjectFileImageAccess:
+ return "can't read object file";
+ default:
+ return "unknown error";
}
- return ofi_msg;
}
/*
@@ -88,15 +81,15 @@ static CONST char* DyldOFIErrorMsg(int err) {
*
* TclpDlopen --
*
- * Dynamically loads a binary code file into memory and returns
- * a handle to the new code.
+ * Dynamically loads a binary code file into memory and returns a handle
+ * to the new code.
*
* Results:
- * A standard Tcl completion code. If an error occurs, an error
- * message is left in the interpreter's result.
+ * A standard Tcl completion code. If an error occurs, an error message
+ * is left in the interpreter's result.
*
* Side effects:
- * New code suddenly appears in memory.
+ * New code suddenly appears in memory.
*
*----------------------------------------------------------------------
*/
@@ -107,90 +100,108 @@ TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
Tcl_Obj *pathPtr; /* Name of the file containing the desired
* code (UTF-8). */
Tcl_LoadHandle *loadHandle; /* Filled with token for dynamically loaded
- * file which will be passed back to
+ * file which will be passed back to
* (*unloadProcPtr)() to unload the file. */
- Tcl_FSUnloadFileProc **unloadProcPtr;
+ Tcl_FSUnloadFileProc **unloadProcPtr;
/* Filled with address of Tcl_FSUnloadFileProc
- * function which should be used for
- * this file. */
+ * function which should be used for this
+ * file. */
{
Tcl_DyldLoadHandle *dyldLoadHandle;
- CONST struct mach_header *dyld_lib;
- NSObjectFileImage dyld_ofi = NULL;
- Tcl_DyldModuleHandle *dyldModuleHandle = NULL;
+ CONST struct mach_header *dyldLibHeader;
+ NSObjectFileImage dyldObjFileImage = NULL;
+ Tcl_DyldModuleHandle *modulePtr = NULL;
CONST char *native;
- /*
- * First try the full path the user gave us. This is particularly
- * important if the cwd is inside a vfs, and we are trying to load
- * using a relative path.
+ /*
+ * First try the full path the user gave us. This is particularly
+ * important if the cwd is inside a vfs, and we are trying to load using a
+ * relative path.
*/
+
native = Tcl_FSGetNativePath(pathPtr);
- dyld_lib = NSAddImage(native,
- NSADDIMAGE_OPTION_WITH_SEARCHING |
- NSADDIMAGE_OPTION_RETURN_ON_ERROR);
-
- if (!dyld_lib) {
- NSLinkEditErrors editError;
- CONST char *name, *msg, *ofi_msg = NULL;
-
- NSLinkEditError(&editError, &errno, &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);
- dyld_lib = NSAddImage(native,
- NSADDIMAGE_OPTION_WITH_SEARCHING |
- NSADDIMAGE_OPTION_RETURN_ON_ERROR);
- Tcl_DStringFree(&ds);
- if (!dyld_lib) {
- NSLinkEditError(&editError, &errno, &name, &msg);
- }
- } else if ((editError == NSLinkEditFileFormatError && errno == EBADMACHO)) {
- /* The requested file was found but was not of type MH_DYLIB,
- * attempt to load it as a MH_BUNDLE: */
- NSObjectFileImageReturnCode err;
- err = NSCreateObjectFileImageFromFile(native, &dyld_ofi);
- ofi_msg = DyldOFIErrorMsg(err);
- }
- if (!dyld_lib && !dyld_ofi) {
- Tcl_AppendResult(interp, msg, (char *) NULL);
- if (ofi_msg) {
- Tcl_AppendResult(interp, "NSCreateObjectFileImageFromFile() error: ",
- ofi_msg, (char *) NULL);
- }
- return TCL_ERROR;
- }
+ dyldLibHeader = NSAddImage(native, NSADDIMAGE_OPTION_WITH_SEARCHING |
+ NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+
+ 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){
+ /*
+ * The requested file was found but was not of type MH_DYLIB,
+ * attempt to load it as a MH_BUNDLE.
+ */
+
+ NSObjectFileImageReturnCode err =
+ NSCreateObjectFileImageFromFile(native, &dyldObjFileImage);
+ objFileImageErrMsg = DyldOFIErrorMsg(err);
+ }
+
+ if (!dyldLibHeader && !dyldObjFileImage) {
+ Tcl_AppendResult(interp, msg, (char *) NULL);
+ if (msg && *msg) {
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ if (objFileImageErrMsg) {
+ Tcl_AppendResult(interp,
+ "NSCreateObjectFileImageFromFile() error: ",
+ objFileImageErrMsg, (char *) NULL);
+ }
+ return TCL_ERROR;
+ }
}
-
- if (dyld_ofi) {
- NSModule module;
- module = NSLinkModule(dyld_ofi, native, NSLINKMODULE_OPTION_BINDNOW |
- NSLINKMODULE_OPTION_RETURN_ON_ERROR);
- NSDestroyObjectFileImage(dyld_ofi);
- if (module) {
- dyldModuleHandle = (Tcl_DyldModuleHandle *)
- ckalloc(sizeof(Tcl_DyldModuleHandle));
- if (!dyldModuleHandle) return TCL_ERROR;
- dyldModuleHandle->module = module;
- dyldModuleHandle->nextModuleHandle = NULL;
- } else {
- NSLinkEditErrors editError;
- CONST char *name, *msg;
- NSLinkEditError(&editError, &errno, &name, &msg);
- Tcl_AppendResult(interp, msg, (char *) NULL);
- return TCL_ERROR;
- }
+
+ 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, (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ modulePtr = (Tcl_DyldModuleHandle *)
+ ckalloc(sizeof(Tcl_DyldModuleHandle));
+ modulePtr->module = module;
+ modulePtr->nextPtr = NULL;
}
- dyldLoadHandle = (Tcl_DyldLoadHandle *) ckalloc(sizeof(Tcl_DyldLoadHandle));
- if (!dyldLoadHandle) return TCL_ERROR;
- dyldLoadHandle->dyld_lib = dyld_lib;
- dyldLoadHandle->firstModuleHandle = dyldModuleHandle;
+
+ dyldLoadHandle = (Tcl_DyldLoadHandle *)
+ ckalloc(sizeof(Tcl_DyldLoadHandle));
+ dyldLoadHandle->dyldLibHeader = dyldLibHeader;
+ dyldLoadHandle->modulePtr = modulePtr;
*loadHandle = (Tcl_LoadHandle) dyldLoadHandle;
*unloadProcPtr = &TclpUnloadFile;
return TCL_OK;
@@ -201,75 +212,85 @@ TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
*
* TclpFindSymbol --
*
- * Looks up a symbol, by name, through a handle associated with
- * a previously loaded piece of code (shared library).
+ * Looks up a symbol, by name, through a handle associated with a
+ * previously loaded piece of code (shared library).
*
* Results:
- * Returns a pointer to the function associated with 'symbol' if
- * it is found. Otherwise returns NULL and may leave an error
- * message in the interp's result.
+ * Returns a pointer to the function associated with 'symbol' if it is
+ * found. Otherwise returns NULL and may leave an error message in the
+ * interp's result.
*
*----------------------------------------------------------------------
*/
+
Tcl_PackageInitProc*
-TclpFindSymbol(interp, loadHandle, symbol)
- Tcl_Interp *interp;
- Tcl_LoadHandle loadHandle;
- CONST char *symbol;
+TclpFindSymbol(interp, loadHandle, symbol)
+ Tcl_Interp *interp; /* For error reporting. */
+ 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.
*/
+
native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
Tcl_DStringInit(&newName);
Tcl_DStringAppend(&newName, "_", 1);
native = Tcl_DStringAppend(&newName, native, -1);
- if (dyldLoadHandle->dyld_lib) {
- nsSymbol = NSLookupSymbolInImage(dyldLoadHandle->dyld_lib, 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 (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.
+ */
+
#ifdef DYLD_SUPPORTS_DYLIB_UNLOADING
- NSModule module = NSModuleForSymbol(nsSymbol);
- Tcl_DyldModuleHandle *dyldModuleHandle = dyldLoadHandle->firstModuleHandle;
- while (dyldModuleHandle) {
- if (module == dyldModuleHandle->module) break;
- dyldModuleHandle = dyldModuleHandle->nextModuleHandle;
- }
- if (!dyldModuleHandle) {
- dyldModuleHandle = (Tcl_DyldModuleHandle *)
- ckalloc(sizeof(Tcl_DyldModuleHandle));
- if (dyldModuleHandle) {
- dyldModuleHandle->module = module;
- dyldModuleHandle->nextModuleHandle =
- dyldLoadHandle->firstModuleHandle;
- dyldLoadHandle->firstModuleHandle = dyldModuleHandle;
- }
- }
+ 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;
+ }
#endif /* DYLD_SUPPORTS_DYLIB_UNLOADING */
- } else {
- NSLinkEditErrors editError;
- CONST char *name, *msg;
- NSLinkEditError(&editError, &errno, &name, &msg);
- Tcl_AppendResult(interp, msg, (char *) NULL);
- }
+
+ } else {
+ NSLinkEditErrors editError;
+ int errorNumber;
+ CONST char *name, *msg;
+
+ NSLinkEditError(&editError, &errorNumber, &name, &msg);
+ Tcl_AppendResult(interp, msg, (char *) NULL);
+ }
} else {
- nsSymbol = NSLookupSymbolInModule(dyldLoadHandle->firstModuleHandle->module,
- native);
+ nsSymbol = NSLookupSymbolInModule(dyldLoadHandle->modulePtr->module,
+ native);
}
- if(nsSymbol) {
- proc = NSAddressOfSymbol(nsSymbol);
+ if (nsSymbol) {
+ proc = NSAddressOfSymbol(nsSymbol);
}
Tcl_DStringFree(&newName);
Tcl_DStringFree(&ds);
-
+
return proc;
}
@@ -278,37 +299,37 @@ TclpFindSymbol(interp, loadHandle, symbol)
*
* TclpUnloadFile --
*
- * Unloads a dynamically loaded binary code file from memory.
- * Code pointers in the formerly loaded file are no longer valid
- * after calling this function.
+ * Unloads a dynamically loaded binary code file from memory. Code
+ * pointers in the formerly loaded file are no longer valid after calling
+ * this function.
*
* Results:
- * None.
+ * None.
*
* Side effects:
- * Code dissapears from memory.
- * Note that dyld currently only supports unloading of binaries of
- * type MH_BUNDLE loaded with NSLinkModule() in TclpDlopen() above.
+ * Code dissapears from memory. Note that dyld currently only supports
+ * unloading of binaries of type MH_BUNDLE loaded with NSLinkModule() in
+ * TclpDlopen() above.
*
*----------------------------------------------------------------------
*/
void
TclpUnloadFile(loadHandle)
- Tcl_LoadHandle loadHandle; /* loadHandle returned by a previous call
- * to TclpDlopen(). The loadHandle is
- * a token that represents the loaded
- * file. */
+ Tcl_LoadHandle loadHandle; /* loadHandle returned by a previous call to
+ * TclpDlopen(). The loadHandle is a token
+ * that represents the loaded file. */
{
Tcl_DyldLoadHandle *dyldLoadHandle = (Tcl_DyldLoadHandle *) loadHandle;
- Tcl_DyldModuleHandle *dyldModuleHandle = dyldLoadHandle->firstModuleHandle;
- void *ptr;
-
- while (dyldModuleHandle) {
- NSUnLinkModule(dyldModuleHandle->module,
- NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);
- ptr = dyldModuleHandle;
- dyldModuleHandle = dyldModuleHandle->nextModuleHandle;
+ Tcl_DyldModuleHandle *modulePtr = dyldLoadHandle->modulePtr;
+
+ while (modulePtr != NULL) {
+ void *ptr;
+
+ NSUnLinkModule(modulePtr->module,
+ NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);
+ ptr = modulePtr;
+ modulePtr = modulePtr->nextPtr;
ckfree(ptr);
}
ckfree((char*) dyldLoadHandle);
@@ -319,27 +340,27 @@ TclpUnloadFile(loadHandle)
*
* TclGuessPackageName --
*
- * If the "load" command is invoked without providing a package
- * name, this procedure is invoked to try to figure it out.
+ * If the "load" command is invoked without providing a package name,
+ * this procedure is invoked to try to figure it out.
*
* Results:
- * Always returns 0 to indicate that we couldn't figure out a
- * package name; generic code will then try to guess the package
- * from the file name. A return value of 1 would have meant that
- * we figured out the package name and put it in bufPtr.
+ * Always returns 0 to indicate that we couldn't figure out a package
+ * name; generic code will then try to guess the package from the file
+ * name. A return value of 1 would have meant that we figured out the
+ * package name and put it in bufPtr.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
int
TclGuessPackageName(fileName, bufPtr)
- CONST char *fileName; /* Name of file containing package (already
- * translated to local form if needed). */
- Tcl_DString *bufPtr; /* Initialized empty dstring. Append
- * package name to this if possible. */
+ CONST char *fileName; /* Name of file containing package (already
+ * translated to local form if needed). */
+ Tcl_DString *bufPtr; /* Initialized empty dstring. Append package
+ * name to this if possible. */
{
return 0;
}
@@ -353,10 +374,10 @@ TclGuessPackageName(fileName, bufPtr)
* Allocate a buffer that can be used with TclpLoadMemory() below.
*
* Results:
- * Pointer to allocated buffer or NULL if an error occurs.
+ * Pointer to allocated buffer or NULL if an error occurs.
*
* Side effects:
- * Buffer is allocated.
+ * Buffer is allocated.
*
*----------------------------------------------------------------------
*/
@@ -364,30 +385,34 @@ TclGuessPackageName(fileName, bufPtr)
void*
TclpLoadMemoryGetBuffer(interp, size)
Tcl_Interp *interp; /* Used for error reporting. */
- int size; /* Size of desired buffer */
+ int size; /* Size of desired buffer. */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- void * buffer = NULL;
-
+ void *buffer = NULL;
+
if (!tsdPtr->haveLoadMemory) {
- /* NSCreateObjectFileImageFromMemory is available but always
- * fails prior to Darwin 7 */
- struct utsname name;
- if (!uname(&name)) {
- long release = strtol(name.release, NULL, 10);
- tsdPtr->haveLoadMemory = (release >= 7) ? 1 : -1;
- }
+ /*
+ * NSCreateObjectFileImageFromMemory is available but always fails
+ * prior to Darwin 7.
+ */
+
+ struct utsname name;
+
+ if (!uname(&name)) {
+ long release = strtol(name.release, NULL, 10);
+ tsdPtr->haveLoadMemory = (release >= 7) ? 1 : -1;
+ }
}
if (tsdPtr->haveLoadMemory > 0) {
- /* We must allocate the buffer using vm_allocate, because
- * NSCreateObjectFileImageFromMemory will dispose of it
- * using vm_deallocate.
- */
- int err = vm_allocate(mach_task_self(),
- (vm_address_t*)&buffer, size, 1);
- if (err) {
- buffer = NULL;
- }
+ /*
+ * We must allocate the buffer using vm_allocate, because
+ * NSCreateObjectFileImageFromMemory will dispose of it using
+ * vm_deallocate.
+ */
+
+ if (vm_allocate(mach_task_self(), (vm_address_t *) &buffer, size, 1)) {
+ buffer = NULL;
+ }
}
return buffer;
}
@@ -397,15 +422,15 @@ TclpLoadMemoryGetBuffer(interp, size)
*
* TclpLoadMemory --
*
- * Dynamically loads binary code file from memory and returns
- * a handle to the new code.
+ * Dynamically loads binary code file from memory and returns a handle to
+ * the new code.
*
* Results:
- * A standard Tcl completion code. If an error occurs, an error
- * message is left in the interpreter's result.
+ * A standard Tcl completion code. If an error occurs, an error message
+ * is left in the interpreter's result.
*
* Side effects:
- * New code is loaded from memory.
+ * New code is loaded from memory.
*
*----------------------------------------------------------------------
*/
@@ -415,60 +440,103 @@ TclpLoadMemory(interp, buffer, size, codeSize, loadHandle, unloadProcPtr)
Tcl_Interp *interp; /* Used for error reporting. */
void *buffer; /* Buffer containing the desired code
* (allocated with TclpLoadMemoryGetBuffer). */
- int size; /* Allocation size of buffer. */
- int codeSize; /* Size of code data read into buffer or -1 if
- * an error occurred and the buffer should
- * just be freed. */
+ int size; /* Allocation size of buffer. */
+ 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
- * file which will be passed back to
+ * file which will be passed back to
* (*unloadProcPtr)() to unload the file. */
- Tcl_FSUnloadFileProc **unloadProcPtr;
+ Tcl_FSUnloadFileProc **unloadProcPtr;
/* Filled with address of Tcl_FSUnloadFileProc
- * function which should be used for
- * this file. */
+ * function which should be used for this
+ * file. */
{
Tcl_DyldLoadHandle *dyldLoadHandle;
- NSObjectFileImage dyld_ofi = NULL;
- Tcl_DyldModuleHandle *dyldModuleHandle;
- CONST char *ofi_msg = NULL;
+ NSObjectFileImage dyldObjFileImage = NULL;
+ Tcl_DyldModuleHandle *modulePtr;
+ NSModule module;
+ CONST char *objFileImageErrMsg = NULL;
+
+ /*
+ * Try to create an object file image that we can load from.
+ */
if (codeSize >= 0) {
- NSObjectFileImageReturnCode err;
- err = NSCreateObjectFileImageFromMemory(buffer, codeSize, &dyld_ofi);
- ofi_msg = DyldOFIErrorMsg(err);
+ NSObjectFileImageReturnCode err = NSObjectFileImageSuccess;
+
+#ifndef __LP64__
+ struct mach_header *mh = buffer;
+ if (codeSize < sizeof(struct mach_header) || mh->magic != MH_MAGIC
+#else
+ struct mach_header_64 *mh = buffer;
+ if (codeSize < sizeof(struct mach_header_64) || mh->magic != MH_MAGIC_64
+#endif
+ || mh->filetype != MH_BUNDLE) {
+ err = NSObjectFileImageInappropriateFile;
+ }
+ if (err == NSObjectFileImageSuccess) {
+ err = NSCreateObjectFileImageFromMemory(buffer, codeSize,
+ &dyldObjFileImage);
+ }
+ objFileImageErrMsg = DyldOFIErrorMsg(err);
}
- if (!dyld_ofi) {
- vm_deallocate(mach_task_self(), (vm_address_t) buffer, size);
- if (ofi_msg) {
- Tcl_AppendResult(interp, "NSCreateObjectFileImageFromFile() error: ",
- ofi_msg, (char *) NULL);
- }
- return TCL_ERROR;
- } else {
- NSModule module;
- module = NSLinkModule(dyld_ofi, "[Memory Based Bundle]",
- NSLINKMODULE_OPTION_BINDNOW |NSLINKMODULE_OPTION_RETURN_ON_ERROR);
- NSDestroyObjectFileImage(dyld_ofi);
- if (module) {
- dyldModuleHandle = (Tcl_DyldModuleHandle *)
- ckalloc(sizeof(Tcl_DyldModuleHandle));
- if (!dyldModuleHandle) return TCL_ERROR;
- dyldModuleHandle->module = module;
- dyldModuleHandle->nextModuleHandle = NULL;
- } else {
- NSLinkEditErrors editError;
- CONST char *name, *msg;
- NSLinkEditError(&editError, &errno, &name, &msg);
- Tcl_AppendResult(interp, msg, (char *) NULL);
- return TCL_ERROR;
- }
+
+ /*
+ * If it went wrong (or we were asked to just deallocate), get rid of the
+ * memory block and create an error message.
+ */
+
+ if (dyldObjFileImage == NULL) {
+ vm_deallocate(mach_task_self(), (vm_address_t) buffer, size);
+ if (objFileImageErrMsg != NULL) {
+ Tcl_AppendResult(interp,
+ "NSCreateObjectFileImageFromFile() error: ",
+ objFileImageErrMsg, (char *) NULL);
+ }
+ return TCL_ERROR;
}
- dyldLoadHandle = (Tcl_DyldLoadHandle *) ckalloc(sizeof(Tcl_DyldLoadHandle));
- if (!dyldLoadHandle) return TCL_ERROR;
- dyldLoadHandle->dyld_lib = NULL;
- dyldLoadHandle->firstModuleHandle = dyldModuleHandle;
+
+ /*
+ * Extract the module we want from the image of the object file.
+ */
+
+ module = NSLinkModule(dyldObjFileImage, "[Memory Based Bundle]",
+ 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, (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Stash the module reference within the load handle we create and return.
+ */
+
+ modulePtr = (Tcl_DyldModuleHandle *) ckalloc(sizeof(Tcl_DyldModuleHandle));
+ modulePtr->module = module;
+ modulePtr->nextPtr = NULL;
+
+ dyldLoadHandle = (Tcl_DyldLoadHandle *)
+ ckalloc(sizeof(Tcl_DyldLoadHandle));
+ dyldLoadHandle->dyldLibHeader = NULL;
+ dyldLoadHandle->modulePtr = modulePtr;
*loadHandle = (Tcl_LoadHandle) dyldLoadHandle;
*unloadProcPtr = &TclpUnloadFile;
return TCL_OK;
}
#endif
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 78
+ * End:
+ */