2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
27 * Copyright 1988-1996, NeXT Software, Inc.
32 #import "objc-private.h"
33 #import <objc/objc-runtime.h>
34 #import <objc/hashtable2.h>
35 #import <objc/Object.h>
36 #import <objc/Protocol.h>
38 #if defined(__MACH__) || defined(WIN32)
39 #import <streams/streams.h>
43 #if !defined(NeXT_PDO)
45 #include <mach-o/dyld.h>
57 #if defined(__hpux__) || defined(hpux)
58 #import "objc_hpux_register_shlib.c"
61 extern char * getsectdatafromheader (const headerType * mhp, const char * segname, const char * sectname, int * size);
64 OBJC_EXPORT void (*callbackFunction)( Class, const char * );
67 struct objc_method_list **get_base_method_list(Class cls) {
68 struct objc_method_list **ptr = ((struct objc_class * )cls)->methodLists;
69 if (!*ptr) return NULL;
70 while ( *ptr != 0 && *ptr != END_OF_METHODS_LIST ) { ptr++; }
76 #if defined(NeXT_PDO) // GENERIC_OBJ_FILE
77 void send_load_message_to_class(Class cls, void *header_addr)
79 struct objc_method_list **mlistp = get_base_method_list(cls->isa);
80 struct objc_method_list *mlist = mlistp ? *mlistp : NULL;
85 class_lookupNamedMethodInMethodList(mlist, "finishLoading:");
87 /* go directly there, we do not want to accidentally send
88 the finishLoading: message to one of its categories...
91 (*load_method)((id)cls, @selector(finishLoading:),
96 void send_load_message_to_category(Category cat, void *header_addr)
98 struct objc_method_list *mlist = cat->class_methods;
104 class_lookupNamedMethodInMethodList(mlist, "finishLoading:");
106 cls = objc_getClass (cat->class_name);
108 /* go directly there, we do not want to accidentally send
109 the finishLoading: message to one of its categories...
112 (*load_method)(cls, @selector(finishLoading:),
116 #endif // GENERIC_OBJ_FILE
118 /**********************************************************************************
121 * NOTE: Loading isn't really thread safe. If a load message recursively calls
122 * objc_loadModules() both sets will be loaded correctly, but if the original
123 * caller calls objc_unloadModules() it will probably unload the wrong modules.
124 * If a load message calls objc_unloadModules(), then it will unload
125 * the modules currently being loaded, which will probably cause a crash.
127 * Error handling is still somewhat crude. If we encounter errors while
128 * linking up classes or categories, we will not recover correctly.
130 * I removed attempts to lock the class hashtable, since this introduced
131 * deadlock which was hard to remove. The only way you can get into trouble
132 * is if one thread loads a module while another thread tries to access the
133 * loaded classes (using objc_lookUpClass) before the load is complete.
134 **********************************************************************************/
135 int objc_loadModule (const char * moduleName,
136 void (*class_callback) (Class, const char *categoryName),
141 #if defined(__MACH__)
142 NSObjectFileImage objectFileImage;
143 NSObjectFileImageReturnCode code;
145 #if defined(WIN32) || defined(__svr4__) || defined(__hpux__) || defined(hpux)
147 void (*save_class_callback) (Class, const char *) = load_class_callback;
150 // So we don't have to check this everywhere
151 if (errorCode == NULL)
152 errorCode = &locErrorCode;
154 #if defined(__MACH__)
155 if (moduleName == NULL)
157 *errorCode = NSObjectFileImageInappropriateFile;
161 if (_dyld_present () == 0)
163 *errorCode = NSObjectFileImageFailure;
167 callbackFunction = class_callback;
168 code = NSCreateObjectFileImageFromFile (moduleName, &objectFileImage);
169 if (code != NSObjectFileImageSuccess)
175 #if !defined(__OBJC_DONT_USE_NEW_NSLINK_OPTION__)
176 if (NSLinkModule(objectFileImage, moduleName, NSLINKMODULE_OPTION_RETURN_ON_ERROR) == NULL) {
177 NSLinkEditErrors error;
179 char *fileName, *errorString;
180 NSLinkEditError(&error, &errorNum, &fileName, &errorString);
181 // These errors may overlap with other errors that objc_loadModule returns in other failure cases.
186 (void)NSLinkModule(objectFileImage, moduleName, NSLINKMODULE_OPTION_NONE);
188 callbackFunction = NULL;
192 if (moduleName == NULL)
198 OBJC_LOCK(&loadLock);
200 #if defined(WIN32) || defined(__svr4__) || defined(__hpux__) || defined(hpux)
202 load_class_callback = class_callback;
205 if ((handle = LoadLibrary (moduleName)) == NULL)
207 FreeLibrary(moduleName);
212 #elif defined(__svr4__)
213 handle = dlopen(moduleName, (RTLD_NOW | RTLD_GLOBAL));
221 objc_register_header(moduleName);
222 objc_finish_header();
226 handle = shl_load(moduleName, BIND_IMMEDIATE | BIND_VERBOSE, 0L);
233 ; // Don't do anything here: the shlib should have been built
234 // with the +I'objc_hpux_register_shlib' option
237 load_class_callback = save_class_callback;
239 #elif defined(NeXT_PDO)
244 OBJC_UNLOCK (&loadLock);
251 /**********************************************************************************
253 **********************************************************************************/
254 /* Lock for dynamic loading and unloading. */
255 static OBJC_DECLARE_LOCK (loadLock);
256 #if defined(NeXT_PDO) // GENERIC_OBJ_FILE
257 void (*load_class_callback) (Class, const char *);
261 long objc_loadModules (char * modlist[],
263 void (*class_callback) (Class, const char *),
264 headerType ** hdr_addr,
274 for (modules = &modlist[0]; *modules != 0; modules++)
276 itWorked = objc_loadModule (*modules, class_callback, &code);
279 #if defined(__MACH__) || defined(WIN32)
281 NXPrintf ((NXStream *) errStream, "objc_loadModules(%s) code = %d\n", *modules, code);
293 /**********************************************************************************
294 * objc_unloadModules.
296 * NOTE: Unloading isn't really thread safe. If an unload message calls
297 * objc_loadModules() or objc_unloadModules(), then the current call
298 * to objc_unloadModules() will probably unload the wrong stuff.
299 **********************************************************************************/
301 long objc_unloadModules (void * errStream,
302 void (*unload_callback) (Class, Category))
304 headerType * header_addr = 0;
307 // TODO: to make unloading work, should get the current header
311 ; // TODO: unload the current header