1996-01-17 00:33:08 +00:00
|
|
|
/* objc-load - Dynamically load in Obj-C modules (Classes, Categories)
|
1995-04-03 20:49:14 +00:00
|
|
|
|
1997-01-06 22:00:31 +00:00
|
|
|
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
1996-01-17 00:33:08 +00:00
|
|
|
Written by: Adam Fedor, Pedja Bogdanovich
|
2005-02-22 11:22:44 +00:00
|
|
|
|
1996-05-12 00:56:10 +00:00
|
|
|
This file is part of the GNUstep Base Library.
|
1996-01-16 23:36:19 +00:00
|
|
|
|
1996-01-17 00:33:08 +00:00
|
|
|
This library is free software; you can redistribute it and/or
|
2007-09-14 11:36:11 +00:00
|
|
|
modify it under the terms of the GNU Lesser General Public
|
1996-01-17 00:33:08 +00:00
|
|
|
License as published by the Free Software Foundation; either
|
2007-09-14 11:36:11 +00:00
|
|
|
version 3 of the License, or (at your option) any later version.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
1996-01-17 00:33:08 +00:00
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2007-09-14 11:36:11 +00:00
|
|
|
You should have received a copy of the GNU Lesser General Public
|
1996-01-17 00:33:08 +00:00
|
|
|
License along with this library; if not, write to the Free
|
2006-05-24 08:27:39 +00:00
|
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02111 USA.
|
2005-02-22 11:22:44 +00:00
|
|
|
*/
|
1995-04-03 20:49:14 +00:00
|
|
|
|
1996-01-16 23:36:19 +00:00
|
|
|
/*
|
|
|
|
CAVEATS:
|
1995-04-03 20:49:14 +00:00
|
|
|
- unloading modules not implemented
|
|
|
|
- would like to raise exceptions without having to turn this into
|
|
|
|
a .m file (right now NSBundle does this for us, ok?)
|
2005-02-22 11:22:44 +00:00
|
|
|
|
1995-04-03 20:49:14 +00:00
|
|
|
*/
|
|
|
|
|
2003-06-07 01:24:41 +00:00
|
|
|
#include "config.h"
|
2002-10-30 02:27:45 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_DLADDR
|
|
|
|
/* Define _GNU_SOURCE because that is required with GNU libc in order
|
|
|
|
* to have dladdr() available. */
|
|
|
|
# define _GNU_SOURCE
|
|
|
|
#endif
|
|
|
|
|
1995-04-03 20:49:14 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <objc/objc-api.h>
|
2001-05-31 22:39:16 +00:00
|
|
|
#ifndef NeXT_RUNTIME
|
2002-10-30 02:27:45 +00:00
|
|
|
# include <objc/objc-list.h>
|
2001-07-11 19:24:25 +00:00
|
|
|
#else
|
2002-10-30 02:27:45 +00:00
|
|
|
# include <objc/objc-load.h>
|
2001-05-31 22:39:16 +00:00
|
|
|
#endif
|
2002-10-30 02:27:45 +00:00
|
|
|
|
2003-07-31 23:49:32 +00:00
|
|
|
#include "objc-load.h"
|
2003-06-07 01:24:41 +00:00
|
|
|
#include "Foundation/NSString.h"
|
|
|
|
#include "Foundation/NSDebug.h"
|
2005-07-25 16:15:37 +00:00
|
|
|
#include "Foundation/NSException.h"
|
1995-04-03 20:49:14 +00:00
|
|
|
|
2006-10-23 14:47:37 +00:00
|
|
|
#include "GSPrivate.h"
|
|
|
|
|
1995-04-03 20:49:14 +00:00
|
|
|
/* include the interface to the dynamic linker */
|
|
|
|
#include "dynamic-load.h"
|
|
|
|
|
|
|
|
/* dynamic_loaded is YES if the dynamic loader was sucessfully initialized. */
|
|
|
|
static BOOL dynamic_loaded;
|
|
|
|
|
|
|
|
/* Our current callback function */
|
2006-10-23 14:47:37 +00:00
|
|
|
static void (*_objc_load_load_callback)(Class, struct objc_category *) = 0;
|
1995-04-03 20:49:14 +00:00
|
|
|
|
|
|
|
/* List of modules we have loaded (by handle) */
|
2001-05-31 22:39:16 +00:00
|
|
|
#ifndef NeXT_RUNTIME
|
1995-04-03 20:49:14 +00:00
|
|
|
static struct objc_list *dynamic_handles = NULL;
|
2001-05-31 22:39:16 +00:00
|
|
|
#endif
|
1995-04-03 20:49:14 +00:00
|
|
|
|
|
|
|
/* Check to see if there are any undefined symbols. Print them out.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
objc_check_undefineds(FILE *errorStream)
|
|
|
|
{
|
2001-08-30 19:18:26 +00:00
|
|
|
int count = __objc_dynamic_undefined_symbol_count();
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
|
|
if (count != 0)
|
2001-08-30 19:18:26 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char **undefs;
|
1995-04-03 20:49:14 +00:00
|
|
|
|
2001-08-30 19:18:26 +00:00
|
|
|
undefs = __objc_dynamic_list_undefined_symbols();
|
|
|
|
if (errorStream)
|
|
|
|
{
|
|
|
|
fprintf(errorStream, "Undefined symbols:\n");
|
|
|
|
}
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
if (errorStream)
|
|
|
|
{
|
|
|
|
fprintf(errorStream, " %s\n", undefs[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
1995-04-03 20:49:14 +00:00
|
|
|
}
|
2001-08-30 19:18:26 +00:00
|
|
|
return 0;
|
1995-04-03 20:49:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialize for dynamic loading */
|
2005-02-22 11:22:44 +00:00
|
|
|
static int
|
1995-04-03 20:49:14 +00:00
|
|
|
objc_initialize_loading(FILE *errorStream)
|
|
|
|
{
|
2006-10-23 14:47:37 +00:00
|
|
|
NSString *path;
|
2006-04-12 19:52:10 +00:00
|
|
|
#ifdef __MINGW32__
|
2006-10-23 14:47:37 +00:00
|
|
|
const unichar *fsPath;
|
2006-04-12 19:52:10 +00:00
|
|
|
#else
|
2006-10-23 14:47:37 +00:00
|
|
|
const char *fsPath;
|
2006-04-12 19:52:10 +00:00
|
|
|
#endif
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2001-08-30 19:18:26 +00:00
|
|
|
dynamic_loaded = NO;
|
2006-10-23 14:47:37 +00:00
|
|
|
path = GSPrivateExecutablePath();
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
|
|
NSDebugFLLog(@"NSBundle",
|
2006-10-23 14:47:37 +00:00
|
|
|
@"Debug (objc-load): initializing dynamic loader for %@", path);
|
|
|
|
|
|
|
|
fsPath = [[path stringByDeletingLastPathComponent] fileSystemRepresentation];
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2006-10-23 14:47:37 +00:00
|
|
|
if (__objc_dynamic_init(fsPath))
|
2001-08-30 19:18:26 +00:00
|
|
|
{
|
|
|
|
if (errorStream)
|
|
|
|
{
|
2005-02-22 11:22:44 +00:00
|
|
|
__objc_dynamic_error(errorStream,
|
2006-10-23 14:47:37 +00:00
|
|
|
"Error (objc-load): Cannot initialize dynamic linker");
|
2001-08-30 19:18:26 +00:00
|
|
|
}
|
|
|
|
return 1;
|
2005-02-22 11:22:44 +00:00
|
|
|
}
|
2001-08-30 19:18:26 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
dynamic_loaded = YES;
|
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2001-08-30 19:18:26 +00:00
|
|
|
return 0;
|
1995-04-03 20:49:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* A callback received from the Object initializer (_objc_exec_class).
|
|
|
|
Do what we need to do and call our own callback.
|
|
|
|
*/
|
2005-02-22 11:22:44 +00:00
|
|
|
static void
|
2001-07-17 02:56:43 +00:00
|
|
|
objc_load_callback(Class class, struct objc_category * category)
|
1995-04-03 20:49:14 +00:00
|
|
|
{
|
2001-08-30 19:18:26 +00:00
|
|
|
if (_objc_load_load_callback)
|
|
|
|
{
|
|
|
|
_objc_load_load_callback(class, category);
|
|
|
|
}
|
1995-04-03 20:49:14 +00:00
|
|
|
}
|
|
|
|
|
2005-11-05 17:41:01 +00:00
|
|
|
#if defined(__MINGW32__)
|
2006-10-23 14:47:37 +00:00
|
|
|
#define FSCHAR unichar
|
2005-11-05 17:41:01 +00:00
|
|
|
#else
|
2006-10-23 14:47:37 +00:00
|
|
|
#define FSCHAR char
|
2005-11-05 17:41:01 +00:00
|
|
|
#endif
|
2006-10-23 14:47:37 +00:00
|
|
|
|
|
|
|
long
|
|
|
|
GSPrivateLoadModule(NSString *filename, FILE *errorStream,
|
|
|
|
void (*loadCallback)(Class, struct objc_category *),
|
|
|
|
void **header, NSString *debugFilename)
|
1995-04-03 20:49:14 +00:00
|
|
|
{
|
2001-07-10 03:23:39 +00:00
|
|
|
#ifdef NeXT_RUNTIME
|
|
|
|
int errcode;
|
|
|
|
dynamic_loaded = YES;
|
2006-10-23 14:47:37 +00:00
|
|
|
return objc_loadModule([filename fileSystemRepresentation],
|
|
|
|
loadCallback, &errcode);
|
2001-07-10 03:23:39 +00:00
|
|
|
#else
|
2001-08-30 19:18:26 +00:00
|
|
|
typedef void (*void_fn)();
|
|
|
|
dl_handle_t handle;
|
2004-10-17 23:22:41 +00:00
|
|
|
void __objc_resolve_class_links(void);
|
1996-05-08 14:56:44 +00:00
|
|
|
#if !defined(__ELF__) && !defined(CON_AUTOLOAD)
|
2001-08-30 19:18:26 +00:00
|
|
|
void_fn *ctor_list;
|
|
|
|
int i;
|
1996-05-08 14:56:44 +00:00
|
|
|
#endif
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2001-08-30 19:18:26 +00:00
|
|
|
if (!dynamic_loaded)
|
|
|
|
{
|
|
|
|
if (objc_initialize_loading(errorStream))
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
1995-04-03 20:49:14 +00:00
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2001-08-30 19:18:26 +00:00
|
|
|
_objc_load_load_callback = loadCallback;
|
|
|
|
_objc_load_callback = objc_load_callback;
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2001-08-30 19:18:26 +00:00
|
|
|
/* Link in the object file */
|
2006-10-23 14:47:37 +00:00
|
|
|
NSDebugFLLog(@"NSBundle", @"Debug (objc-load): Linking file %@\n", filename);
|
|
|
|
handle = __objc_dynamic_link((FSCHAR*)[filename fileSystemRepresentation],
|
|
|
|
1, (FSCHAR*)[debugFilename fileSystemRepresentation]);
|
2005-02-22 11:22:44 +00:00
|
|
|
if (handle == 0)
|
2001-08-30 19:18:26 +00:00
|
|
|
{
|
|
|
|
if (errorStream)
|
|
|
|
{
|
|
|
|
__objc_dynamic_error(errorStream, "Error (objc-load)");
|
|
|
|
}
|
2001-08-30 19:24:49 +00:00
|
|
|
_objc_load_load_callback = 0;
|
|
|
|
_objc_load_callback = 0;
|
2001-08-30 19:18:26 +00:00
|
|
|
return 1;
|
1995-04-03 20:49:14 +00:00
|
|
|
}
|
2001-08-30 19:18:26 +00:00
|
|
|
dynamic_handles = list_cons(handle, dynamic_handles);
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2001-08-30 19:18:26 +00:00
|
|
|
/* If there are any undefined symbols, we can't load the bundle */
|
2005-02-22 11:22:44 +00:00
|
|
|
if (objc_check_undefineds(errorStream))
|
2001-08-30 19:18:26 +00:00
|
|
|
{
|
|
|
|
__objc_dynamic_unlink(handle);
|
2001-08-30 19:24:49 +00:00
|
|
|
_objc_load_load_callback = 0;
|
|
|
|
_objc_load_callback = 0;
|
2001-08-30 19:18:26 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
1996-01-16 23:36:19 +00:00
|
|
|
#if !defined(__ELF__) && !defined(CON_AUTOLOAD)
|
2001-08-30 19:18:26 +00:00
|
|
|
/* Get the constructor list and load in the objects */
|
|
|
|
ctor_list = (void_fn *)__objc_dynamic_find_symbol(handle, CTOR_LIST);
|
2005-02-22 11:22:44 +00:00
|
|
|
if (!ctor_list)
|
2001-08-30 19:18:26 +00:00
|
|
|
{
|
|
|
|
if (errorStream)
|
|
|
|
{
|
2005-02-22 11:22:44 +00:00
|
|
|
fprintf(errorStream,
|
2006-10-23 14:47:37 +00:00
|
|
|
"Error (objc-load): Cannot load objects (no CTOR list)\n");
|
2001-08-30 19:18:26 +00:00
|
|
|
}
|
2001-08-30 19:24:49 +00:00
|
|
|
_objc_load_load_callback = 0;
|
|
|
|
_objc_load_callback = 0;
|
2001-08-30 19:18:26 +00:00
|
|
|
return 1;
|
1995-04-03 20:49:14 +00:00
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2001-08-30 19:18:26 +00:00
|
|
|
NSDebugFLLog(@"NSBundle",
|
2006-10-23 14:47:37 +00:00
|
|
|
@"Debug (objc-load): %d modules\n", (int)ctor_list[0]);
|
2005-02-22 11:22:44 +00:00
|
|
|
for (i = 1; ctor_list[i]; i++)
|
2001-08-30 19:18:26 +00:00
|
|
|
{
|
|
|
|
NSDebugFLLog(@"NSBundle",
|
2006-10-23 14:47:37 +00:00
|
|
|
@"Debug (objc-load): Invoking CTOR %p\n", ctor_list[i]);
|
2001-08-30 19:18:26 +00:00
|
|
|
ctor_list[i]();
|
1995-04-03 20:49:14 +00:00
|
|
|
}
|
1995-05-26 17:54:55 +00:00
|
|
|
#endif /* not __ELF__ */
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2004-10-17 23:22:41 +00:00
|
|
|
__objc_resolve_class_links(); /* fill in subclass_list and sibling_class */
|
2001-08-30 19:18:26 +00:00
|
|
|
_objc_load_callback = 0;
|
|
|
|
_objc_load_load_callback = 0;
|
|
|
|
return 0;
|
2004-10-17 23:22:41 +00:00
|
|
|
#endif /* not NeXT_RUNTIME */
|
1995-04-03 20:49:14 +00:00
|
|
|
}
|
|
|
|
|
2005-02-22 11:22:44 +00:00
|
|
|
long
|
2006-10-23 14:47:37 +00:00
|
|
|
GSPrivateUnloadModule(FILE *errorStream,
|
|
|
|
void (*unloadCallback)(Class, struct objc_category *))
|
1995-04-03 20:49:14 +00:00
|
|
|
{
|
2001-08-30 19:18:26 +00:00
|
|
|
if (!dynamic_loaded)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2001-08-30 19:18:26 +00:00
|
|
|
if (errorStream)
|
|
|
|
{
|
|
|
|
fprintf(errorStream, "Warning: unloading modules not implemented\n");
|
|
|
|
}
|
|
|
|
return 0;
|
1995-04-03 20:49:14 +00:00
|
|
|
}
|
|
|
|
|
2000-10-28 21:58:48 +00:00
|
|
|
|
2005-10-11 19:09:26 +00:00
|
|
|
#ifdef __MINGW32__
|
2005-07-25 16:15:37 +00:00
|
|
|
NSString *
|
2006-10-23 14:47:37 +00:00
|
|
|
GSPrivateSymbolPath(Class theClass, Category *theCategory)
|
2005-07-25 16:15:37 +00:00
|
|
|
{
|
2005-11-05 16:20:19 +00:00
|
|
|
unichar buf[MAX_PATH];
|
2005-07-25 16:15:37 +00:00
|
|
|
MEMORY_BASIC_INFORMATION memInfo;
|
2006-10-23 14:47:37 +00:00
|
|
|
NSCAssert(!theCategory, @"GSPrivateSymbolPath doesn't support categories");
|
2005-07-25 16:15:37 +00:00
|
|
|
|
|
|
|
VirtualQueryEx(GetCurrentProcess(), theClass, &memInfo, sizeof(memInfo));
|
2005-11-05 16:20:19 +00:00
|
|
|
if (GetModuleFileNameW(memInfo.AllocationBase, buf, sizeof(buf)))
|
2005-07-25 16:15:37 +00:00
|
|
|
{
|
2005-11-05 16:20:19 +00:00
|
|
|
return [NSString stringWithCharacters: buf length: wcslen(buf)];
|
2005-07-25 16:15:37 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#else
|
2000-10-28 21:58:48 +00:00
|
|
|
NSString *
|
2006-10-23 14:47:37 +00:00
|
|
|
GSPrivateSymbolPath(Class theClass, Category *theCategory)
|
2000-10-28 21:58:48 +00:00
|
|
|
{
|
|
|
|
const char *ret;
|
|
|
|
char buf[125], *p = buf;
|
|
|
|
int len = strlen(theClass->name);
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2002-10-30 02:27:45 +00:00
|
|
|
if (theCategory == NULL)
|
2000-10-28 21:58:48 +00:00
|
|
|
{
|
2002-10-30 02:27:45 +00:00
|
|
|
if (len + sizeof(char)*19 > sizeof(buf))
|
2000-10-28 21:58:48 +00:00
|
|
|
{
|
2006-05-24 08:27:39 +00:00
|
|
|
p = objc_malloc(len + sizeof(char)*19);
|
2000-10-28 21:58:48 +00:00
|
|
|
|
2002-10-30 02:27:45 +00:00
|
|
|
if (p == NULL)
|
2000-10-28 21:58:48 +00:00
|
|
|
{
|
|
|
|
fprintf(stderr, "Unable to allocate memory !!");
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-10-30 02:27:45 +00:00
|
|
|
memcpy(p, "__objc_class_name_", sizeof(char)*18);
|
|
|
|
memcpy(&p[18*sizeof(char)], theClass->name,
|
|
|
|
strlen(theClass->name) + 1);
|
2000-10-28 21:58:48 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
len += strlen(theCategory->category_name);
|
|
|
|
|
2001-08-30 19:18:26 +00:00
|
|
|
if (len + sizeof(char)*23 > sizeof(buf))
|
2000-10-28 21:58:48 +00:00
|
|
|
{
|
2006-05-24 08:27:39 +00:00
|
|
|
p = objc_malloc(len + sizeof(char)*23);
|
2000-10-28 21:58:48 +00:00
|
|
|
|
2002-10-30 02:27:45 +00:00
|
|
|
if (p == NULL)
|
2000-10-28 21:58:48 +00:00
|
|
|
{
|
|
|
|
fprintf(stderr, "Unable to allocate memory !!");
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-10-30 02:27:45 +00:00
|
|
|
memcpy(p, "__objc_category_name_", sizeof(char)*21);
|
|
|
|
memcpy(&p[21*sizeof(char)], theCategory->class_name,
|
|
|
|
strlen(theCategory->class_name) + 1);
|
|
|
|
memcpy(&p[strlen(p)], "_", 2*sizeof(char));
|
|
|
|
memcpy(&p[strlen(p)], theCategory->category_name,
|
|
|
|
strlen(theCategory->category_name) + 1);
|
2000-10-28 21:58:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = __objc_dynamic_get_symbol_path(0, p);
|
|
|
|
|
|
|
|
if (p != buf)
|
2001-08-30 19:18:26 +00:00
|
|
|
{
|
2006-05-24 08:27:39 +00:00
|
|
|
objc_free(p);
|
2001-08-30 19:18:26 +00:00
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2000-10-28 21:58:48 +00:00
|
|
|
if (ret)
|
2001-08-30 19:18:26 +00:00
|
|
|
{
|
2006-10-09 14:00:01 +00:00
|
|
|
return [NSString stringWithUTF8String: ret];
|
2001-08-30 19:18:26 +00:00
|
|
|
}
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2000-10-28 21:58:48 +00:00
|
|
|
return nil;
|
|
|
|
}
|
2005-07-25 16:15:37 +00:00
|
|
|
#endif
|