]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (c) 1999-2001, 2004-2007 Apple Inc. All Rights Reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | ||
24 | /* | |
25 | * objc-load.m | |
26 | * Copyright 1988-1996, NeXT Software, Inc. | |
27 | * Author: s. naroff | |
28 | * | |
29 | */ | |
30 | ||
31 | #if !__OBJC2__ | |
32 | ||
33 | #import "objc-private.h" | |
34 | #import <objc/objc-runtime.h> | |
35 | #import <objc/hashtable2.h> | |
36 | #import <objc/Object.h> | |
37 | #include <mach-o/dyld.h> | |
38 | ||
39 | ||
40 | extern void (*callbackFunction)( Class, const char * ); | |
41 | ||
42 | ||
43 | /********************************************************************************** | |
44 | * objc_loadModule. | |
45 | * | |
46 | * NOTE: Loading isn't really thread safe. If a load message recursively calls | |
47 | * objc_loadModules() both sets will be loaded correctly, but if the original | |
48 | * caller calls objc_unloadModules() it will probably unload the wrong modules. | |
49 | * If a load message calls objc_unloadModules(), then it will unload | |
50 | * the modules currently being loaded, which will probably cause a crash. | |
51 | * | |
52 | * Error handling is still somewhat crude. If we encounter errors while | |
53 | * linking up classes or categories, we will not recover correctly. | |
54 | * | |
55 | * I removed attempts to lock the class hashtable, since this introduced | |
56 | * deadlock which was hard to remove. The only way you can get into trouble | |
57 | * is if one thread loads a module while another thread tries to access the | |
58 | * loaded classes (using objc_lookUpClass) before the load is complete. | |
59 | **********************************************************************************/ | |
60 | int objc_loadModule(const char *moduleName, void (*class_callback) (Class, const char *categoryName), int *errorCode) | |
61 | { | |
62 | int successFlag = 1; | |
63 | int locErrorCode; | |
64 | NSObjectFileImage objectFileImage; | |
65 | NSObjectFileImageReturnCode code; | |
66 | ||
67 | // So we don't have to check this everywhere | |
68 | if (errorCode == NULL) | |
69 | errorCode = &locErrorCode; | |
70 | ||
71 | if (moduleName == NULL) | |
72 | { | |
73 | *errorCode = NSObjectFileImageInappropriateFile; | |
74 | return 0; | |
75 | } | |
76 | ||
77 | if (_dyld_present () == 0) | |
78 | { | |
79 | *errorCode = NSObjectFileImageFailure; | |
80 | return 0; | |
81 | } | |
82 | ||
83 | callbackFunction = class_callback; | |
84 | code = NSCreateObjectFileImageFromFile (moduleName, &objectFileImage); | |
85 | if (code != NSObjectFileImageSuccess) | |
86 | { | |
87 | *errorCode = code; | |
88 | return 0; | |
89 | } | |
90 | ||
91 | if (NSLinkModule(objectFileImage, moduleName, NSLINKMODULE_OPTION_RETURN_ON_ERROR) == NULL) { | |
92 | NSLinkEditErrors error; | |
93 | int errorNum; | |
94 | const char *fileName, *errorString; | |
95 | NSLinkEditError(&error, &errorNum, &fileName, &errorString); | |
96 | // These errors may overlap with other errors that objc_loadModule returns in other failure cases. | |
97 | *errorCode = error; | |
98 | return 0; | |
99 | } | |
100 | callbackFunction = NULL; | |
101 | ||
102 | ||
103 | return successFlag; | |
104 | } | |
105 | ||
106 | /********************************************************************************** | |
107 | * objc_loadModules. | |
108 | **********************************************************************************/ | |
109 | /* Lock for dynamic loading and unloading. */ | |
110 | // static OBJC_DECLARE_LOCK (loadLock); | |
111 | ||
112 | ||
113 | long objc_loadModules (char * modlist[], | |
114 | void * errStream, | |
115 | void (*class_callback) (Class, const char *), | |
116 | headerType ** hdr_addr, | |
117 | char * debug_file) | |
118 | { | |
119 | char ** modules; | |
120 | int code; | |
121 | int itWorked; | |
122 | ||
123 | if (modlist == 0) | |
124 | return 0; | |
125 | ||
126 | for (modules = &modlist[0]; *modules != 0; modules++) | |
127 | { | |
128 | itWorked = objc_loadModule (*modules, class_callback, &code); | |
129 | if (itWorked == 0) | |
130 | { | |
131 | //if (errStream) | |
132 | // NXPrintf ((NXStream *) errStream, "objc_loadModules(%s) code = %d\n", *modules, code); | |
133 | return 1; | |
134 | } | |
135 | ||
136 | if (hdr_addr) | |
137 | *(hdr_addr++) = 0; | |
138 | } | |
139 | ||
140 | return 0; | |
141 | } | |
142 | ||
143 | /********************************************************************************** | |
144 | * objc_unloadModules. | |
145 | * | |
146 | * NOTE: Unloading isn't really thread safe. If an unload message calls | |
147 | * objc_loadModules() or objc_unloadModules(), then the current call | |
148 | * to objc_unloadModules() will probably unload the wrong stuff. | |
149 | **********************************************************************************/ | |
150 | ||
151 | long objc_unloadModules (void * errStream, | |
152 | void (*unload_callback) (Class, Category)) | |
153 | { | |
154 | headerType * header_addr = 0; | |
155 | int errflag = 0; | |
156 | ||
157 | // TODO: to make unloading work, should get the current header | |
158 | ||
159 | if (header_addr) | |
160 | { | |
161 | ; // TODO: unload the current header | |
162 | } | |
163 | else | |
164 | { | |
165 | errflag = 1; | |
166 | } | |
167 | ||
168 | return errflag; | |
169 | } | |
170 | ||
171 | #endif |