os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/unix/tclLoadDyld.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/*
sl@0
     2
 * tclLoadDyld.c --
sl@0
     3
 *
sl@0
     4
 *	This procedure provides a version of the TclLoadFile that works with
sl@0
     5
 *	Apple's dyld dynamic loading.
sl@0
     6
 *	Original version of his file (now superseded long ago) provided by
sl@0
     7
 *	Wilfredo Sanchez (wsanchez@apple.com).
sl@0
     8
 *
sl@0
     9
 * Copyright (c) 1995 Apple Computer, Inc.
sl@0
    10
 * Copyright (c) 2001-2007 Daniel A. Steffen <das@users.sourceforge.net>
sl@0
    11
 *
sl@0
    12
 * See the file "license.terms" for information on usage and redistribution of
sl@0
    13
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
sl@0
    14
 *
sl@0
    15
 * RCS: @(#) $Id: tclLoadDyld.c,v 1.14.2.9 2007/04/29 02:20:16 das Exp $
sl@0
    16
 */
sl@0
    17
sl@0
    18
#include "tclInt.h"
sl@0
    19
#include "tclPort.h"
sl@0
    20
#include <mach-o/dyld.h>
sl@0
    21
#include <mach-o/fat.h>
sl@0
    22
#include <mach-o/swap.h>
sl@0
    23
#include <mach-o/arch.h>
sl@0
    24
#include <libkern/OSByteOrder.h>
sl@0
    25
#undef panic
sl@0
    26
#include <mach/mach.h>
sl@0
    27
sl@0
    28
#ifndef MODULE_SCOPE
sl@0
    29
#define MODULE_SCOPE extern
sl@0
    30
#endif
sl@0
    31
sl@0
    32
typedef struct Tcl_DyldModuleHandle {
sl@0
    33
    struct Tcl_DyldModuleHandle *nextPtr;
sl@0
    34
    NSModule module;
sl@0
    35
} Tcl_DyldModuleHandle;
sl@0
    36
sl@0
    37
typedef struct Tcl_DyldLoadHandle {
sl@0
    38
    CONST struct mach_header *dyldLibHeader;
sl@0
    39
    Tcl_DyldModuleHandle *modulePtr;
sl@0
    40
} Tcl_DyldLoadHandle;
sl@0
    41
sl@0
    42
#ifdef TCL_LOAD_FROM_MEMORY
sl@0
    43
MODULE_SCOPE long tclMacOSXDarwinRelease;
sl@0
    44
#endif
sl@0
    45

sl@0
    46
/*
sl@0
    47
 *----------------------------------------------------------------------
sl@0
    48
 *
sl@0
    49
 * DyldOFIErrorMsg --
sl@0
    50
 *
sl@0
    51
 *	Converts a numerical NSObjectFileImage error into an error message
sl@0
    52
 *	string.
sl@0
    53
 *
sl@0
    54
 * Results:
sl@0
    55
 *	Error message string.
sl@0
    56
 *
sl@0
    57
 * Side effects:
sl@0
    58
 *	None.
sl@0
    59
 *
sl@0
    60
 *----------------------------------------------------------------------
sl@0
    61
 */
sl@0
    62
sl@0
    63
static CONST char*
sl@0
    64
DyldOFIErrorMsg(
sl@0
    65
    int err)
sl@0
    66
{
sl@0
    67
    switch(err) {
sl@0
    68
    case NSObjectFileImageSuccess:
sl@0
    69
	return NULL;
sl@0
    70
    case NSObjectFileImageFailure:
sl@0
    71
	return "object file setup failure";
sl@0
    72
    case NSObjectFileImageInappropriateFile:
sl@0
    73
	return "not a Mach-O MH_BUNDLE file";
sl@0
    74
    case NSObjectFileImageArch:
sl@0
    75
	return "no object for this architecture";
sl@0
    76
    case NSObjectFileImageFormat:
sl@0
    77
	return "bad object file format";
sl@0
    78
    case NSObjectFileImageAccess:
sl@0
    79
	return "can't read object file";
sl@0
    80
    default:
sl@0
    81
	return "unknown error";
sl@0
    82
    }
sl@0
    83
}
sl@0
    84

sl@0
    85
/*
sl@0
    86
 *----------------------------------------------------------------------
sl@0
    87
 *
sl@0
    88
 * TclpDlopen --
sl@0
    89
 *
sl@0
    90
 *	Dynamically loads a binary code file into memory and returns a handle
sl@0
    91
 *	to the new code.
sl@0
    92
 *
sl@0
    93
 * Results:
sl@0
    94
 *	A standard Tcl completion code. If an error occurs, an error message
sl@0
    95
 *	is left in the interpreter's result.
sl@0
    96
 *
sl@0
    97
 * Side effects:
sl@0
    98
 *	New code suddenly appears in memory.
sl@0
    99
 *
sl@0
   100
 *----------------------------------------------------------------------
sl@0
   101
 */
sl@0
   102
sl@0
   103
MODULE_SCOPE int
sl@0
   104
TclpDlopen(
sl@0
   105
    Tcl_Interp *interp,		/* Used for error reporting. */
sl@0
   106
    Tcl_Obj *pathPtr,		/* Name of the file containing the desired
sl@0
   107
				 * code (UTF-8). */
sl@0
   108
    Tcl_LoadHandle *loadHandle,	/* Filled with token for dynamically loaded
sl@0
   109
				 * file which will be passed back to
sl@0
   110
				 * (*unloadProcPtr)() to unload the file. */
sl@0
   111
    Tcl_FSUnloadFileProc **unloadProcPtr)
sl@0
   112
				/* Filled with address of Tcl_FSUnloadFileProc
sl@0
   113
				 * function which should be used for this
sl@0
   114
				 * file. */
sl@0
   115
{
sl@0
   116
    Tcl_DyldLoadHandle *dyldLoadHandle;
sl@0
   117
    CONST struct mach_header *dyldLibHeader;
sl@0
   118
    NSObjectFileImage dyldObjFileImage = NULL;
sl@0
   119
    Tcl_DyldModuleHandle *modulePtr = NULL;
sl@0
   120
    CONST char *native;
sl@0
   121
sl@0
   122
    /*
sl@0
   123
     * First try the full path the user gave us. This is particularly
sl@0
   124
     * important if the cwd is inside a vfs, and we are trying to load using a
sl@0
   125
     * relative path.
sl@0
   126
     */
sl@0
   127
sl@0
   128
    native = Tcl_FSGetNativePath(pathPtr);
sl@0
   129
    dyldLibHeader = NSAddImage(native, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
sl@0
   130
sl@0
   131
    if (!dyldLibHeader) {
sl@0
   132
	NSLinkEditErrors editError;
sl@0
   133
	int errorNumber;
sl@0
   134
	CONST char *name, *msg, *objFileImageErrMsg = NULL;
sl@0
   135
sl@0
   136
	NSLinkEditError(&editError, &errorNumber, &name, &msg);
sl@0
   137
sl@0
   138
	if (editError == NSLinkEditFileAccessError) {
sl@0
   139
	    /*
sl@0
   140
	     * The requested file was not found. Let the OS loader examine the
sl@0
   141
	     * binary search path for whatever string the user gave us which
sl@0
   142
	     * hopefully refers to a file on the binary path.
sl@0
   143
	     */
sl@0
   144
sl@0
   145
	    Tcl_DString ds;
sl@0
   146
	    char *fileName = Tcl_GetString(pathPtr);
sl@0
   147
	    CONST char *native =
sl@0
   148
		    Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
sl@0
   149
sl@0
   150
	    dyldLibHeader = NSAddImage(native, NSADDIMAGE_OPTION_WITH_SEARCHING
sl@0
   151
		    | NSADDIMAGE_OPTION_RETURN_ON_ERROR);
sl@0
   152
	    Tcl_DStringFree(&ds);
sl@0
   153
	    if (!dyldLibHeader) {
sl@0
   154
		NSLinkEditError(&editError, &errorNumber, &name, &msg);
sl@0
   155
	    }
sl@0
   156
	} else if ((editError == NSLinkEditFileFormatError
sl@0
   157
		&& errorNumber == EBADMACHO)
sl@0
   158
		|| editError == NSLinkEditOtherError){
sl@0
   159
	    /*
sl@0
   160
	     * The requested file was found but was not of type MH_DYLIB,
sl@0
   161
	     * attempt to load it as a MH_BUNDLE.
sl@0
   162
	     */
sl@0
   163
sl@0
   164
	    NSObjectFileImageReturnCode err =
sl@0
   165
		    NSCreateObjectFileImageFromFile(native, &dyldObjFileImage);
sl@0
   166
	    objFileImageErrMsg = DyldOFIErrorMsg(err);
sl@0
   167
	}
sl@0
   168
sl@0
   169
	if (!dyldLibHeader && !dyldObjFileImage) {
sl@0
   170
	    Tcl_AppendResult(interp, msg, NULL);
sl@0
   171
	    if (msg && *msg) {
sl@0
   172
		Tcl_AppendResult(interp, "\n", NULL);
sl@0
   173
	    }
sl@0
   174
	    if (objFileImageErrMsg) {
sl@0
   175
		Tcl_AppendResult(interp,
sl@0
   176
			"NSCreateObjectFileImageFromFile() error: ",
sl@0
   177
			objFileImageErrMsg, NULL);
sl@0
   178
	    }
sl@0
   179
	    return TCL_ERROR;
sl@0
   180
	}
sl@0
   181
    }
sl@0
   182
sl@0
   183
    if (dyldObjFileImage) {
sl@0
   184
	NSModule module;
sl@0
   185
sl@0
   186
	module = NSLinkModule(dyldObjFileImage, native,
sl@0
   187
		NSLINKMODULE_OPTION_BINDNOW
sl@0
   188
		| NSLINKMODULE_OPTION_RETURN_ON_ERROR);
sl@0
   189
	NSDestroyObjectFileImage(dyldObjFileImage);
sl@0
   190
sl@0
   191
	if (!module) {
sl@0
   192
	    NSLinkEditErrors editError;
sl@0
   193
	    int errorNumber;
sl@0
   194
	    CONST char *name, *msg;
sl@0
   195
sl@0
   196
	    NSLinkEditError(&editError, &errorNumber, &name, &msg);
sl@0
   197
	    Tcl_AppendResult(interp, msg, NULL);
sl@0
   198
	    return TCL_ERROR;
sl@0
   199
	}
sl@0
   200
sl@0
   201
	modulePtr = (Tcl_DyldModuleHandle *)
sl@0
   202
		ckalloc(sizeof(Tcl_DyldModuleHandle));
sl@0
   203
	modulePtr->module = module;
sl@0
   204
	modulePtr->nextPtr = NULL;
sl@0
   205
    }
sl@0
   206
sl@0
   207
    dyldLoadHandle = (Tcl_DyldLoadHandle *)
sl@0
   208
	    ckalloc(sizeof(Tcl_DyldLoadHandle));
sl@0
   209
    dyldLoadHandle->dyldLibHeader = dyldLibHeader;
sl@0
   210
    dyldLoadHandle->modulePtr = modulePtr;
sl@0
   211
    *loadHandle = (Tcl_LoadHandle) dyldLoadHandle;
sl@0
   212
    *unloadProcPtr = &TclpUnloadFile;
sl@0
   213
    return TCL_OK;
sl@0
   214
}
sl@0
   215

sl@0
   216
/*
sl@0
   217
 *----------------------------------------------------------------------
sl@0
   218
 *
sl@0
   219
 * TclpFindSymbol --
sl@0
   220
 *
sl@0
   221
 *	Looks up a symbol, by name, through a handle associated with a
sl@0
   222
 *	previously loaded piece of code (shared library).
sl@0
   223
 *
sl@0
   224
 * Results:
sl@0
   225
 *	Returns a pointer to the function associated with 'symbol' if it is
sl@0
   226
 *	found. Otherwise returns NULL and may leave an error message in the
sl@0
   227
 *	interp's result.
sl@0
   228
 *
sl@0
   229
 *----------------------------------------------------------------------
sl@0
   230
 */
sl@0
   231
sl@0
   232
MODULE_SCOPE Tcl_PackageInitProc *
sl@0
   233
TclpFindSymbol(
sl@0
   234
    Tcl_Interp *interp,		/* For error reporting. */
sl@0
   235
    Tcl_LoadHandle loadHandle,	/* Handle from TclpDlopen. */
sl@0
   236
    CONST char *symbol)		/* Symbol name to look up. */
sl@0
   237
{
sl@0
   238
    NSSymbol nsSymbol;
sl@0
   239
    CONST char *native;
sl@0
   240
    Tcl_DString newName, ds;
sl@0
   241
    Tcl_PackageInitProc *proc = NULL;
sl@0
   242
    Tcl_DyldLoadHandle *dyldLoadHandle = (Tcl_DyldLoadHandle *) loadHandle;
sl@0
   243
sl@0
   244
    /*
sl@0
   245
     * dyld adds an underscore to the beginning of symbol names.
sl@0
   246
     */
sl@0
   247
sl@0
   248
    native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
sl@0
   249
    Tcl_DStringInit(&newName);
sl@0
   250
    Tcl_DStringAppend(&newName, "_", 1);
sl@0
   251
    native = Tcl_DStringAppend(&newName, native, -1);
sl@0
   252
sl@0
   253
    if (dyldLoadHandle->dyldLibHeader) {
sl@0
   254
	nsSymbol = NSLookupSymbolInImage(dyldLoadHandle->dyldLibHeader, native,
sl@0
   255
		NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW |
sl@0
   256
		NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
sl@0
   257
	if (nsSymbol) {
sl@0
   258
	    /*
sl@0
   259
	     * Until dyld supports unloading of MY_DYLIB binaries, the
sl@0
   260
	     * following is not needed.
sl@0
   261
	     */
sl@0
   262
sl@0
   263
#ifdef DYLD_SUPPORTS_DYLIB_UNLOADING
sl@0
   264
	    NSModule module = NSModuleForSymbol(nsSymbol);
sl@0
   265
	    Tcl_DyldModuleHandle *modulePtr = dyldLoadHandle->modulePtr;
sl@0
   266
sl@0
   267
	    while (modulePtr != NULL) {
sl@0
   268
		if (module == modulePtr->module) {
sl@0
   269
		    break;
sl@0
   270
		}
sl@0
   271
		modulePtr = modulePtr->nextPtr;
sl@0
   272
	    }
sl@0
   273
	    if (modulePtr == NULL) {
sl@0
   274
		modulePtr = (Tcl_DyldModuleHandle *)
sl@0
   275
			ckalloc(sizeof(Tcl_DyldModuleHandle));
sl@0
   276
		modulePtr->module = module;
sl@0
   277
		modulePtr->nextPtr = dyldLoadHandle->modulePtr;
sl@0
   278
		dyldLoadHandle->modulePtr = modulePtr;
sl@0
   279
	    }
sl@0
   280
#endif /* DYLD_SUPPORTS_DYLIB_UNLOADING */
sl@0
   281
sl@0
   282
	} else {
sl@0
   283
	    NSLinkEditErrors editError;
sl@0
   284
	    int errorNumber;
sl@0
   285
	    CONST char *name, *msg;
sl@0
   286
sl@0
   287
	    NSLinkEditError(&editError, &errorNumber, &name, &msg);
sl@0
   288
	    Tcl_AppendResult(interp, msg, NULL);
sl@0
   289
	}
sl@0
   290
    } else {
sl@0
   291
	nsSymbol = NSLookupSymbolInModule(dyldLoadHandle->modulePtr->module,
sl@0
   292
		native);
sl@0
   293
    }
sl@0
   294
    if (nsSymbol) {
sl@0
   295
	proc = NSAddressOfSymbol(nsSymbol);
sl@0
   296
    }
sl@0
   297
    Tcl_DStringFree(&newName);
sl@0
   298
    Tcl_DStringFree(&ds);
sl@0
   299
sl@0
   300
    return proc;
sl@0
   301
}
sl@0
   302

sl@0
   303
/*
sl@0
   304
 *----------------------------------------------------------------------
sl@0
   305
 *
sl@0
   306
 * TclpUnloadFile --
sl@0
   307
 *
sl@0
   308
 *	Unloads a dynamically loaded binary code file from memory. Code
sl@0
   309
 *	pointers in the formerly loaded file are no longer valid after calling
sl@0
   310
 *	this function.
sl@0
   311
 *
sl@0
   312
 * Results:
sl@0
   313
 *	None.
sl@0
   314
 *
sl@0
   315
 * Side effects:
sl@0
   316
 *	Code dissapears from memory. Note that dyld currently only supports
sl@0
   317
 *	unloading of binaries of type MH_BUNDLE loaded with NSLinkModule() in
sl@0
   318
 *	TclpDlopen() above.
sl@0
   319
 *
sl@0
   320
 *----------------------------------------------------------------------
sl@0
   321
 */
sl@0
   322
sl@0
   323
MODULE_SCOPE void
sl@0
   324
TclpUnloadFile(
sl@0
   325
    Tcl_LoadHandle loadHandle)	/* loadHandle returned by a previous call to
sl@0
   326
				 * TclpDlopen(). The loadHandle is a token
sl@0
   327
				 * that represents the loaded file. */
sl@0
   328
{
sl@0
   329
    Tcl_DyldLoadHandle *dyldLoadHandle = (Tcl_DyldLoadHandle *) loadHandle;
sl@0
   330
    Tcl_DyldModuleHandle *modulePtr = dyldLoadHandle->modulePtr;
sl@0
   331
sl@0
   332
    while (modulePtr != NULL) {
sl@0
   333
	void *ptr;
sl@0
   334
sl@0
   335
	NSUnLinkModule(modulePtr->module,
sl@0
   336
		NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);
sl@0
   337
	ptr = modulePtr;
sl@0
   338
	modulePtr = modulePtr->nextPtr;
sl@0
   339
	ckfree(ptr);
sl@0
   340
    }
sl@0
   341
    ckfree((char*) dyldLoadHandle);
sl@0
   342
}
sl@0
   343

sl@0
   344
/*
sl@0
   345
 *----------------------------------------------------------------------
sl@0
   346
 *
sl@0
   347
 * TclGuessPackageName --
sl@0
   348
 *
sl@0
   349
 *	If the "load" command is invoked without providing a package name,
sl@0
   350
 *	this procedure is invoked to try to figure it out.
sl@0
   351
 *
sl@0
   352
 * Results:
sl@0
   353
 *	Always returns 0 to indicate that we couldn't figure out a package
sl@0
   354
 *	name; generic code will then try to guess the package from the file
sl@0
   355
 *	name. A return value of 1 would have meant that we figured out the
sl@0
   356
 *	package name and put it in bufPtr.
sl@0
   357
 *
sl@0
   358
 * Side effects:
sl@0
   359
 *	None.
sl@0
   360
 *
sl@0
   361
 *----------------------------------------------------------------------
sl@0
   362
 */
sl@0
   363
sl@0
   364
int
sl@0
   365
TclGuessPackageName(
sl@0
   366
    CONST char *fileName,	/* Name of file containing package (already
sl@0
   367
				 * translated to local form if needed). */
sl@0
   368
    Tcl_DString *bufPtr)	/* Initialized empty dstring. Append package
sl@0
   369
				 * name to this if possible. */
sl@0
   370
{
sl@0
   371
    return 0;
sl@0
   372
}
sl@0
   373

sl@0
   374
#ifdef TCL_LOAD_FROM_MEMORY
sl@0
   375
/*
sl@0
   376
 *----------------------------------------------------------------------
sl@0
   377
 *
sl@0
   378
 * TclpLoadMemoryGetBuffer --
sl@0
   379
 *
sl@0
   380
 *	Allocate a buffer that can be used with TclpLoadMemory() below.
sl@0
   381
 *
sl@0
   382
 * Results:
sl@0
   383
 *	Pointer to allocated buffer or NULL if an error occurs.
sl@0
   384
 *
sl@0
   385
 * Side effects:
sl@0
   386
 *	Buffer is allocated.
sl@0
   387
 *
sl@0
   388
 *----------------------------------------------------------------------
sl@0
   389
 */
sl@0
   390
sl@0
   391
MODULE_SCOPE void *
sl@0
   392
TclpLoadMemoryGetBuffer(
sl@0
   393
    Tcl_Interp *interp,		/* Used for error reporting. */
sl@0
   394
    int size)			/* Size of desired buffer. */
sl@0
   395
{
sl@0
   396
    void *buffer = NULL;
sl@0
   397
sl@0
   398
    /*
sl@0
   399
     * NSCreateObjectFileImageFromMemory is available but always fails
sl@0
   400
     * prior to Darwin 7.
sl@0
   401
     */
sl@0
   402
    if (tclMacOSXDarwinRelease >= 7) {
sl@0
   403
	/*
sl@0
   404
	 * We must allocate the buffer using vm_allocate, because
sl@0
   405
	 * NSCreateObjectFileImageFromMemory will dispose of it using
sl@0
   406
	 * vm_deallocate.
sl@0
   407
	 */
sl@0
   408
sl@0
   409
	if (vm_allocate(mach_task_self(), (vm_address_t *) &buffer, size, 1)) {
sl@0
   410
	    buffer = NULL;
sl@0
   411
	}
sl@0
   412
    }
sl@0
   413
    return buffer;
sl@0
   414
}
sl@0
   415

sl@0
   416
/*
sl@0
   417
 *----------------------------------------------------------------------
sl@0
   418
 *
sl@0
   419
 * TclpLoadMemory --
sl@0
   420
 *
sl@0
   421
 *	Dynamically loads binary code file from memory and returns a handle to
sl@0
   422
 *	the new code.
sl@0
   423
 *
sl@0
   424
 * Results:
sl@0
   425
 *	A standard Tcl completion code. If an error occurs, an error message
sl@0
   426
 *	is left in the interpreter's result.
sl@0
   427
 *
sl@0
   428
 * Side effects:
sl@0
   429
 *	New code is loaded from memory.
sl@0
   430
 *
sl@0
   431
 *----------------------------------------------------------------------
sl@0
   432
 */
sl@0
   433
sl@0
   434
MODULE_SCOPE int
sl@0
   435
TclpLoadMemory(
sl@0
   436
    Tcl_Interp *interp,		/* Used for error reporting. */
sl@0
   437
    void *buffer,		/* Buffer containing the desired code
sl@0
   438
				 * (allocated with TclpLoadMemoryGetBuffer). */
sl@0
   439
    int size,			/* Allocation size of buffer. */
sl@0
   440
    int codeSize,		/* Size of code data read into buffer or -1 if
sl@0
   441
				 * an error occurred and the buffer should
sl@0
   442
				 * just be freed. */
sl@0
   443
    Tcl_LoadHandle *loadHandle,	/* Filled with token for dynamically loaded
sl@0
   444
				 * file which will be passed back to
sl@0
   445
				 * (*unloadProcPtr)() to unload the file. */
sl@0
   446
    Tcl_FSUnloadFileProc **unloadProcPtr)
sl@0
   447
				/* Filled with address of Tcl_FSUnloadFileProc
sl@0
   448
				 * function which should be used for this
sl@0
   449
				 * file. */
sl@0
   450
{
sl@0
   451
    Tcl_DyldLoadHandle *dyldLoadHandle;
sl@0
   452
    NSObjectFileImage dyldObjFileImage = NULL;
sl@0
   453
    Tcl_DyldModuleHandle *modulePtr;
sl@0
   454
    NSModule module;
sl@0
   455
    CONST char *objFileImageErrMsg = NULL;
sl@0
   456
sl@0
   457
    /*
sl@0
   458
     * Try to create an object file image that we can load from.
sl@0
   459
     */
sl@0
   460
sl@0
   461
    if (codeSize >= 0) {
sl@0
   462
	NSObjectFileImageReturnCode err = NSObjectFileImageSuccess;
sl@0
   463
	CONST struct fat_header *fh = buffer;
sl@0
   464
	uint32_t ms = 0;
sl@0
   465
#ifndef __LP64__
sl@0
   466
	CONST struct mach_header *mh = NULL;
sl@0
   467
	#define mh_magic OSSwapHostToBigInt32(MH_MAGIC)
sl@0
   468
	#define mh_size  sizeof(struct mach_header)
sl@0
   469
#else
sl@0
   470
	CONST struct mach_header_64 *mh = NULL;
sl@0
   471
	#define mh_magic OSSwapHostToBigInt32(MH_MAGIC_64)
sl@0
   472
	#define mh_size  sizeof(struct mach_header_64)
sl@0
   473
#endif
sl@0
   474
	
sl@0
   475
	if ((size_t) codeSize >= sizeof(struct fat_header)
sl@0
   476
		&& fh->magic == OSSwapHostToBigInt32(FAT_MAGIC)) {
sl@0
   477
	    /*
sl@0
   478
	     * Fat binary, try to find mach_header for our architecture
sl@0
   479
	     */
sl@0
   480
	    uint32_t fh_nfat_arch = OSSwapBigToHostInt32(fh->nfat_arch);
sl@0
   481
	    
sl@0
   482
	    if ((size_t) codeSize >= sizeof(struct fat_header) + 
sl@0
   483
		    fh_nfat_arch * sizeof(struct fat_arch)) {
sl@0
   484
		void *fatarchs = (char*)buffer + sizeof(struct fat_header);
sl@0
   485
		CONST NXArchInfo *arch = NXGetLocalArchInfo();
sl@0
   486
		struct fat_arch *fa;
sl@0
   487
		
sl@0
   488
		if (fh->magic != FAT_MAGIC) {
sl@0
   489
		    swap_fat_arch(fatarchs, fh_nfat_arch, arch->byteorder);
sl@0
   490
		}
sl@0
   491
		fa = NXFindBestFatArch(arch->cputype, arch->cpusubtype,
sl@0
   492
			fatarchs, fh_nfat_arch);
sl@0
   493
		if (fa) {
sl@0
   494
		    mh = (void*)((char*)buffer + fa->offset);
sl@0
   495
		    ms = fa->size;
sl@0
   496
		} else {
sl@0
   497
		    err = NSObjectFileImageInappropriateFile;
sl@0
   498
		}
sl@0
   499
		if (fh->magic != FAT_MAGIC) {
sl@0
   500
		    swap_fat_arch(fatarchs, fh_nfat_arch, arch->byteorder);
sl@0
   501
		}
sl@0
   502
	    } else {
sl@0
   503
		err = NSObjectFileImageInappropriateFile;
sl@0
   504
	    }
sl@0
   505
	} else {
sl@0
   506
	    /*
sl@0
   507
	     * Thin binary
sl@0
   508
	     */
sl@0
   509
	    mh = buffer;
sl@0
   510
	    ms = codeSize;
sl@0
   511
	}
sl@0
   512
	if (ms && !(ms >= mh_size && mh->magic == mh_magic &&
sl@0
   513
		 mh->filetype == OSSwapHostToBigInt32(MH_BUNDLE))) {
sl@0
   514
	    err = NSObjectFileImageInappropriateFile;
sl@0
   515
	}
sl@0
   516
	if (err == NSObjectFileImageSuccess) {
sl@0
   517
	    err = NSCreateObjectFileImageFromMemory(buffer, codeSize,
sl@0
   518
		    &dyldObjFileImage);
sl@0
   519
	}
sl@0
   520
	objFileImageErrMsg = DyldOFIErrorMsg(err);
sl@0
   521
    }
sl@0
   522
sl@0
   523
    /*
sl@0
   524
     * If it went wrong (or we were asked to just deallocate), get rid of the
sl@0
   525
     * memory block and create an error message.
sl@0
   526
     */
sl@0
   527
sl@0
   528
    if (dyldObjFileImage == NULL) {
sl@0
   529
	vm_deallocate(mach_task_self(), (vm_address_t) buffer, size);
sl@0
   530
	if (objFileImageErrMsg != NULL) {
sl@0
   531
	    Tcl_AppendResult(interp,
sl@0
   532
		    "NSCreateObjectFileImageFromMemory() error: ",
sl@0
   533
		    objFileImageErrMsg, NULL);
sl@0
   534
	}
sl@0
   535
	return TCL_ERROR;
sl@0
   536
    }
sl@0
   537
sl@0
   538
    /*
sl@0
   539
     * Extract the module we want from the image of the object file.
sl@0
   540
     */
sl@0
   541
sl@0
   542
    module = NSLinkModule(dyldObjFileImage, "[Memory Based Bundle]",
sl@0
   543
	    NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
sl@0
   544
    NSDestroyObjectFileImage(dyldObjFileImage);
sl@0
   545
sl@0
   546
    if (!module) {
sl@0
   547
	NSLinkEditErrors editError;
sl@0
   548
	int errorNumber;
sl@0
   549
	CONST char *name, *msg;
sl@0
   550
sl@0
   551
	NSLinkEditError(&editError, &errorNumber, &name, &msg);
sl@0
   552
	Tcl_AppendResult(interp, msg, NULL);
sl@0
   553
	return TCL_ERROR;
sl@0
   554
    }
sl@0
   555
sl@0
   556
    /*
sl@0
   557
     * Stash the module reference within the load handle we create and return.
sl@0
   558
     */
sl@0
   559
sl@0
   560
    modulePtr = (Tcl_DyldModuleHandle *) ckalloc(sizeof(Tcl_DyldModuleHandle));
sl@0
   561
    modulePtr->module = module;
sl@0
   562
    modulePtr->nextPtr = NULL;
sl@0
   563
sl@0
   564
    dyldLoadHandle = (Tcl_DyldLoadHandle *)
sl@0
   565
	    ckalloc(sizeof(Tcl_DyldLoadHandle));
sl@0
   566
    dyldLoadHandle->dyldLibHeader = NULL;
sl@0
   567
    dyldLoadHandle->modulePtr = modulePtr;
sl@0
   568
    *loadHandle = (Tcl_LoadHandle) dyldLoadHandle;
sl@0
   569
    *unloadProcPtr = &TclpUnloadFile;
sl@0
   570
    return TCL_OK;
sl@0
   571
}
sl@0
   572
#endif
sl@0
   573

sl@0
   574
/*
sl@0
   575
 * Local Variables:
sl@0
   576
 * mode: c
sl@0
   577
 * c-basic-offset: 4
sl@0
   578
 * fill-column: 78
sl@0
   579
 * End:
sl@0
   580
 */