]>
Commit | Line | Data |
---|---|---|
13d88034 | 1 | /* |
b3962a83 | 2 | * Copyright (c) 1999-2007 Apple Inc. All Rights Reserved. |
13d88034 | 3 | * |
b3962a83 | 4 | * @APPLE_LICENSE_HEADER_START@ |
390d5862 A |
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. | |
13d88034 A |
12 | * |
13 | * The Original Code and all software distributed under the License are | |
390d5862 | 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
13d88034 A |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
390d5862 A |
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. | |
13d88034 A |
20 | * |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | /* | |
24 | * objc-private.h | |
25 | * Copyright 1988-1996, NeXT Software, Inc. | |
26 | */ | |
27 | ||
28 | #if !defined(_OBJC_PRIVATE_H_) | |
b3962a83 A |
29 | #define _OBJC_PRIVATE_H_ |
30 | ||
31 | #import <pthread.h> | |
32 | #import <errno.h> | |
33 | #import <limits.h> | |
34 | #import <unistd.h> | |
35 | #import <sys/time.h> | |
36 | #import <stdlib.h> | |
37 | #import <stdarg.h> | |
38 | #import <stdio.h> | |
39 | #import <string.h> | |
40 | #import <ctype.h> | |
41 | #import <mach-o/loader.h> | |
42 | #import <malloc/malloc.h> | |
43 | #import <libkern/OSAtomic.h> | |
44 | #import <dlfcn.h> | |
45 | ||
46 | #import "objc.h" | |
47 | #import "runtime.h" | |
48 | #import "maptable.h" | |
49 | #import "auto_zone.h" | |
50 | ||
51 | struct old_category; | |
52 | struct old_method_list; | |
53 | typedef struct { | |
54 | IMP imp; | |
55 | SEL sel; | |
56 | } message_ref; | |
57 | ||
58 | #if __OBJC2__ | |
59 | ||
60 | typedef struct objc_module *Module; | |
61 | typedef struct objc_cache *Cache; | |
13d88034 | 62 | |
b3962a83 | 63 | #endif |
13d88034 | 64 | |
13d88034 | 65 | |
b3962a83 A |
66 | #if OLD |
67 | ||
68 | struct old_class { | |
69 | struct old_class *isa; | |
70 | struct old_class *super_class; | |
71 | const char *name; | |
72 | long version; | |
73 | long info; | |
74 | long instance_size; | |
75 | struct old_ivar_list *ivars; | |
76 | struct old_method_list **methodLists; | |
77 | Cache cache; | |
78 | struct old_protocol_list *protocols; | |
79 | // CLS_EXT only | |
80 | const char *ivar_layout; | |
81 | struct old_class_ext *ext; | |
82 | }; | |
83 | ||
84 | struct old_class_ext { | |
85 | uint32_t size; | |
86 | const char *weak_ivar_layout; | |
87 | struct objc_property_list **propertyLists; | |
88 | }; | |
89 | ||
90 | struct old_category { | |
91 | char *category_name; | |
92 | char *class_name; | |
93 | struct old_method_list *instance_methods; | |
94 | struct old_method_list *class_methods; | |
95 | struct old_protocol_list *protocols; | |
96 | uint32_t size; | |
97 | struct objc_property_list *instance_properties; | |
98 | }; | |
99 | ||
100 | struct old_ivar { | |
101 | char *ivar_name; | |
102 | char *ivar_type; | |
103 | int ivar_offset; | |
104 | #ifdef __LP64__ | |
105 | int space; | |
106 | #endif | |
107 | }; | |
13d88034 | 108 | |
b3962a83 A |
109 | struct old_ivar_list { |
110 | int ivar_count; | |
111 | #ifdef __LP64__ | |
112 | int space; | |
113 | #endif | |
114 | /* variable length structure */ | |
115 | struct old_ivar ivar_list[1]; | |
116 | }; | |
13d88034 | 117 | |
13d88034 | 118 | |
b3962a83 A |
119 | struct old_method { |
120 | SEL method_name; | |
121 | char *method_types; | |
122 | IMP method_imp; | |
123 | }; | |
13d88034 | 124 | |
b3962a83 A |
125 | // Fixed-up method lists get mlist->obsolete = _OBJC_FIXED_UP. |
126 | #define _OBJC_FIXED_UP ((void *)1771) | |
127 | ||
128 | struct old_method_list { | |
129 | struct old_method_list *obsolete; | |
130 | ||
131 | int method_count; | |
132 | #ifdef __LP64__ | |
133 | int space; | |
134 | #endif | |
135 | /* variable length structure */ | |
136 | struct old_method method_list[1]; | |
137 | }; | |
138 | ||
139 | struct old_protocol { | |
140 | Class isa; | |
141 | const char *protocol_name; | |
142 | struct old_protocol_list *protocol_list; | |
143 | struct objc_method_description_list *instance_methods; | |
144 | struct objc_method_description_list *class_methods; | |
145 | }; | |
146 | ||
147 | struct old_protocol_list { | |
148 | struct old_protocol_list *next; | |
149 | long count; | |
150 | struct old_protocol *list[1]; | |
151 | }; | |
152 | ||
153 | struct old_protocol_ext { | |
154 | uint32_t size; | |
155 | struct objc_method_description_list *optional_instance_methods; | |
156 | struct objc_method_description_list *optional_class_methods; | |
157 | struct objc_property_list *instance_properties; | |
158 | }; | |
159 | ||
160 | #endif | |
161 | ||
162 | typedef objc_property_t Property; | |
163 | ||
164 | struct objc_property { | |
165 | const char *name; | |
166 | const char *attributes; | |
167 | }; | |
168 | ||
169 | struct objc_property_list { | |
170 | uint32_t entsize; | |
171 | uint32_t count; | |
172 | struct objc_property first; | |
173 | }; | |
174 | ||
175 | ||
176 | #import "objc-api.h" | |
177 | #import "objc-config.h" | |
178 | #import "hashtable2.h" | |
179 | ||
180 | #import "Object.h" | |
181 | ||
182 | #define mutex_alloc() (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t)) | |
183 | #define mutex_init(m) pthread_mutex_init(m, NULL) | |
184 | #define mutex_lock(m) pthread_mutex_lock(m) | |
185 | #define mutex_try_lock(m) (! pthread_mutex_trylock(m)) | |
186 | #define mutex_unlock(m) pthread_mutex_unlock(m) | |
187 | #define mutex_clear(m) | |
188 | #define mutex_t pthread_mutex_t* | |
189 | #define mutex MUTEX_DEFINE_ERROR | |
13d88034 A |
190 | |
191 | ||
192 | /* Opaque cookie used in _getObjc... routines. File format independant. | |
193 | * This is used in place of the mach_header. In fact, when compiling | |
194 | * for NEXTSTEP, this is really a (struct mach_header *). | |
195 | * | |
196 | * had been: typedef void *objc_header; | |
197 | */ | |
b3962a83 | 198 | #ifndef __LP64__ |
1f20c7a7 | 199 | typedef struct mach_header headerType; |
b3962a83 A |
200 | typedef struct segment_command segmentType; |
201 | #else | |
202 | typedef struct mach_header_64 headerType; | |
203 | typedef struct segment_command_64 segmentType; | |
204 | #endif | |
13d88034 | 205 | |
390d5862 A |
206 | typedef struct { |
207 | uint32_t version; // currently 0 | |
208 | uint32_t flags; | |
209 | } objc_image_info; | |
210 | ||
211 | // masks for objc_image_info.flags | |
212 | #define OBJC_IMAGE_IS_REPLACEMENT (1<<0) | |
2bfd4448 | 213 | #define OBJC_IMAGE_SUPPORTS_GC (1<<1) |
b3962a83 | 214 | #define OBJC_IMAGE_REQUIRES_GC (1<<2) |
2bfd4448 A |
215 | |
216 | ||
390d5862 A |
217 | #define _objcHeaderIsReplacement(h) ((h)->info && ((h)->info->flags & OBJC_IMAGE_IS_REPLACEMENT)) |
218 | ||
219 | /* OBJC_IMAGE_IS_REPLACEMENT: | |
220 | Don't load any classes | |
221 | Don't load any categories | |
222 | Do fix up selector refs (@selector points to them) | |
223 | Do fix up class refs (@class and objc_msgSend points to them) | |
224 | Do fix up protocols (@protocol points to them) | |
2bfd4448 | 225 | Do fix up super_class pointers in classes ([super ...] points to them) |
390d5862 A |
226 | Future: do load new classes? |
227 | Future: do load new categories? | |
228 | Future: do insert new methods on existing classes? | |
229 | Future: do insert new methods on existing categories? | |
230 | */ | |
231 | ||
b3962a83 A |
232 | #define _objcInfoSupportsGC(info) (((info)->flags & OBJC_IMAGE_SUPPORTS_GC) ? 1 : 0) |
233 | #define _objcInfoRequiresGC(info) (((info)->flags & OBJC_IMAGE_REQUIRES_GC) ? 1 : 0) | |
234 | #define _objcHeaderSupportsGC(h) ((h)->info && _objcInfoSupportsGC((h)->info)) | |
235 | #define _objcHeaderRequiresGC(h) ((h)->info && _objcInfoRequiresGC((h)->info)) | |
2bfd4448 A |
236 | |
237 | /* OBJC_IMAGE_SUPPORTS_GC: | |
238 | was compiled with -fobjc-gc flag, regardless of whether write-barriers were issued | |
239 | if executable image compiled this way, then all subsequent libraries etc. must also be this way | |
240 | */ | |
390d5862 | 241 | |
b3962a83 A |
242 | |
243 | typedef struct _header_info | |
244 | { | |
245 | struct _header_info *next; | |
246 | const headerType * mhdr; | |
247 | ptrdiff_t image_slide; | |
248 | const segmentType * objcSegmentHeader; | |
249 | const segmentType * dataSegmentHeader; | |
250 | struct objc_module *mod_ptr; | |
251 | size_t mod_count; | |
252 | const objc_image_info *info; | |
253 | Dl_info dl_info; | |
254 | BOOL allClassesRealized; | |
255 | } header_info; | |
256 | ||
257 | ||
258 | extern objc_image_info *_getObjcImageInfo(const headerType *head, ptrdiff_t slide, size_t *size); | |
259 | extern const segmentType *getsegbynamefromheader(const headerType *head, const char *segname); | |
260 | extern const char *_getObjcHeaderName(const headerType *head); | |
261 | extern ptrdiff_t _getImageSlide(const headerType *header); | |
262 | ||
263 | extern Module _getObjcModules(const headerType *head, ptrdiff_t slide, size_t *count); | |
264 | extern SEL *_getObjcSelectorRefs(const header_info *hi, size_t *count); | |
265 | #if !__OBJC2__ | |
266 | extern struct old_protocol *_getObjcProtocols(const header_info *head, size_t *count); | |
267 | extern struct old_class **_getObjcClassRefs(const header_info *hi, size_t *count); | |
268 | extern const char *_getObjcClassNames(const header_info *hi, size_t *size); | |
269 | #endif | |
270 | ||
271 | #if __OBJC2__ | |
272 | extern SEL *_getObjc2SelectorRefs(const header_info *hi, size_t *count); | |
273 | extern message_ref *_getObjc2MessageRefs(const header_info *hi, size_t *count);extern struct class_t **_getObjc2ClassRefs(const header_info *hi, size_t *count); | |
274 | extern struct class_t **_getObjc2SuperRefs(const header_info *hi, size_t *count); | |
275 | extern struct class_t **_getObjc2ClassList(const header_info *hi, size_t *count); | |
276 | extern struct class_t **_getObjc2NonlazyClassList(const header_info *hi, size_t *count); | |
277 | extern struct category_t **_getObjc2CategoryList(const header_info *hi, size_t *count); | |
278 | extern struct category_t **_getObjc2NonlazyCategoryList(const header_info *hi, size_t *count); | |
279 | extern struct protocol_t **_getObjc2ProtocolList(const header_info *head, size_t *count); | |
280 | extern struct protocol_t **_getObjc2ProtocolRefs(const header_info *head, size_t *count); | |
281 | #endif | |
282 | ||
283 | #define END_OF_METHODS_LIST ((struct old_method_list*)-1) | |
284 | ||
285 | OBJC_EXPORT header_info *_objc_headerStart (); | |
286 | ||
287 | OBJC_EXPORT const char *_nameForHeader(const headerType*); | |
288 | ||
289 | OBJC_EXPORT SEL sel_registerNameNoLock(const char *str, BOOL copy); | |
290 | OBJC_EXPORT void sel_lock(void); | |
291 | OBJC_EXPORT void sel_unlock(void); | |
292 | ||
293 | /* optional malloc zone for runtime data */ | |
294 | OBJC_EXPORT malloc_zone_t *_objc_internal_zone(void); | |
295 | OBJC_EXPORT void *_malloc_internal(size_t size); | |
296 | OBJC_EXPORT void *_calloc_internal(size_t count, size_t size); | |
297 | OBJC_EXPORT void *_realloc_internal(void *ptr, size_t size); | |
298 | OBJC_EXPORT char *_strdup_internal(const char *str); | |
299 | OBJC_EXPORT char *_strdupcat_internal(const char *s1, const char *s2); | |
300 | OBJC_EXPORT void *_memdup_internal(const void *mem, size_t size); | |
301 | OBJC_EXPORT void _free_internal(void *ptr); | |
302 | ||
303 | #if !__OBJC2__ | |
304 | OBJC_EXPORT Class objc_getOrigClass (const char *name); | |
305 | OBJC_EXPORT IMP lookupNamedMethodInMethodList(struct old_method_list *mlist, const char *meth_name); | |
306 | OBJC_EXPORT void _objc_insertMethods(struct old_class *cls, struct old_method_list *mlist, struct old_category *cat); | |
307 | OBJC_EXPORT void _objc_removeMethods(struct old_class *cls, struct old_method_list *mlist); | |
308 | OBJC_EXPORT void _objc_flush_caches (Class cls); | |
309 | extern void _class_addProperties(struct old_class *cls, struct objc_property_list *additions); | |
310 | extern void change_class_references(struct old_class *imposter, struct old_class *original, struct old_class *copy, BOOL changeSuperRefs); | |
311 | extern void flush_marked_caches(void); | |
312 | extern void set_superclass(struct old_class *cls, struct old_class *supercls); | |
313 | #endif | |
314 | ||
315 | OBJC_EXPORT IMP _cache_getImp(Class cls, SEL sel); | |
316 | OBJC_EXPORT Method _cache_getMethod(Class cls, SEL sel, IMP objc_msgForward_imp); | |
317 | ||
318 | /* message dispatcher */ | |
319 | OBJC_EXPORT IMP _class_lookupMethodAndLoadCache(Class, SEL); | |
320 | OBJC_EXPORT id _objc_msgForward (id self, SEL sel, ...); | |
321 | extern id _objc_ignored_method(id self, SEL _cmd); | |
322 | ||
323 | /* errors */ | |
324 | OBJC_EXPORT void _objc_fatal(const char *fmt, ...) __attribute__((noreturn, format (printf, 1, 2))); | |
325 | OBJC_EXPORT void __objc_error(id, const char *, ...) __attribute__((format (printf, 2, 3))); | |
326 | OBJC_EXPORT void _objc_inform(const char *fmt, ...) __attribute__((format (printf, 1, 2))); | |
327 | OBJC_EXPORT void _objc_inform_on_crash(const char *fmt, ...) __attribute__((format (printf, 1, 2))); | |
328 | OBJC_EXPORT void _objc_inform_now_and_on_crash(const char *fmt, ...) __attribute__((format (printf, 1, 2))); | |
329 | OBJC_EXPORT void _objc_warn_deprecated(const char *old, const char *new) __attribute__((noinline)); | |
330 | OBJC_EXPORT void _objc_error(id, const char *, va_list); | |
331 | ||
332 | /* magic */ | |
333 | OBJC_EXPORT Class _objc_getFreedObjectClass (void); | |
2bfd4448 | 334 | #ifndef OBJC_INSTRUMENTED |
b3962a83 | 335 | OBJC_EXPORT const struct objc_cache _objc_empty_cache; |
2bfd4448 | 336 | #else |
b3962a83 | 337 | OBJC_EXPORT struct objc_cache _objc_empty_cache; |
2bfd4448 | 338 | #endif |
b3962a83 A |
339 | #if __OBJC2__ |
340 | extern IMP _objc_empty_vtable[128]; | |
2bfd4448 A |
341 | #endif |
342 | ||
b3962a83 A |
343 | /* map table additions */ |
344 | extern void *NXMapKeyCopyingInsert(NXMapTable *table, const void *key, const void *value); | |
345 | extern void *NXMapKeyFreeingRemove(NXMapTable *table, const void *key); | |
346 | ||
347 | /* locking */ | |
348 | #define OBJC_DECLARE_LOCK(MTX) pthread_mutex_t MTX = PTHREAD_MUTEX_INITIALIZER | |
349 | #ifdef NDEBUG | |
350 | #define OBJC_LOCK(MUTEX) mutex_lock (MUTEX) | |
351 | #define OBJC_UNLOCK(MUTEX) mutex_unlock (MUTEX) | |
352 | #define OBJC_CHECK_LOCKED(MUTEX) do { } while (0) | |
353 | #define OBJC_CHECK_UNLOCKED(MUTEX) do { } while (0) | |
354 | #else | |
355 | #define OBJC_LOCK(MUTEX) _lock_debug (MUTEX, #MUTEX) | |
356 | #define OBJC_UNLOCK(MUTEX) _unlock_debug (MUTEX, #MUTEX) | |
357 | #define OBJC_CHECK_LOCKED(MUTEX) _checklock_debug (MUTEX, #MUTEX) | |
358 | #define OBJC_CHECK_UNLOCKED(MUTEX) _checkunlock_debug (MUTEX, #MUTEX) | |
359 | #endif | |
2bfd4448 | 360 | |
b3962a83 A |
361 | OBJC_EXPORT pthread_mutex_t classLock; |
362 | OBJC_EXPORT pthread_mutex_t methodListLock; | |
13d88034 | 363 | |
b3962a83 | 364 | OBJC_EXPORT NXHashTable *class_hash; |
13d88034 | 365 | |
b3962a83 A |
366 | /* nil handler object */ |
367 | OBJC_EXPORT id _objc_nilReceiver; | |
368 | OBJC_EXPORT id _objc_setNilReceiver(id newNilReceiver); | |
369 | OBJC_EXPORT id _objc_getNilReceiver(void); | |
370 | ||
371 | /* forward handler functions */ | |
372 | OBJC_EXPORT void *_objc_forward_handler; | |
373 | OBJC_EXPORT void *_objc_forward_stret_handler; | |
374 | ||
375 | /* C++ interoperability */ | |
376 | OBJC_EXPORT SEL cxx_construct_sel; | |
377 | OBJC_EXPORT SEL cxx_destruct_sel; | |
378 | OBJC_EXPORT const char *cxx_construct_name; | |
379 | OBJC_EXPORT const char *cxx_destruct_name; | |
380 | ||
381 | /* GC and RTP startup */ | |
382 | OBJC_EXPORT void gc_init(BOOL on); | |
383 | OBJC_EXPORT void rtp_init(void); | |
384 | ||
385 | /* Exceptions */ | |
386 | struct alt_handler_list; | |
387 | OBJC_EXPORT void exception_init(void); | |
388 | OBJC_EXPORT void _destroyAltHandlerList(struct alt_handler_list *list); | |
389 | ||
390 | /* Write barrier implementations */ | |
391 | OBJC_EXPORT id objc_assign_strongCast_gc(id val, id *dest); | |
392 | OBJC_EXPORT id objc_assign_global_gc(id val, id *dest); | |
393 | OBJC_EXPORT id objc_assign_ivar_gc(id value, id dest, ptrdiff_t offset); | |
394 | OBJC_EXPORT id objc_assign_strongCast_non_gc(id value, id *dest); | |
395 | OBJC_EXPORT id objc_assign_global_non_gc(id value, id *dest); | |
396 | OBJC_EXPORT id objc_assign_ivar_non_gc(id value, id dest, ptrdiff_t offset); | |
397 | ||
398 | /* | |
399 | objc_assign_ivar, objc_assign_global, and objc_assign_strongCast MUST NOT be called directly | |
400 | from inside libobjc. They live in the data segment, and must be called through the | |
401 | following pointer(s) for libobjc to exist in the shared cache. | |
402 | ||
403 | Note: If we build with GC enabled, gcc will emit calls to the original functions, which will break this. | |
404 | */ | |
405 | ||
406 | extern id (*objc_assign_ivar_internal)(id, id, ptrdiff_t); | |
407 | ||
408 | /* Code modification */ | |
409 | OBJC_EXPORT size_t objc_branch_size(void *entry, void *target); | |
410 | OBJC_EXPORT size_t objc_write_branch(void *entry, void *target); | |
411 | OBJC_EXPORT size_t objc_cond_branch_size(void *entry, void *target, unsigned cond); | |
412 | OBJC_EXPORT size_t objc_write_cond_branch(void *entry, void *target, unsigned cond); | |
413 | #if defined(__ppc__) || defined(__ppc64__) | |
414 | #define COND_ALWAYS 0x02800000 /* BO=10100, BI=00000 */ | |
415 | #define COND_NE 0x00820000 /* BO=00100, BI=00010 */ | |
416 | #elif defined(__i386__) || defined(__x86_64__) | |
417 | #define COND_ALWAYS 0xE9 /* JMP rel32 */ | |
418 | #define COND_NE 0x85 /* JNE rel32 (0F 85) */ | |
419 | #endif | |
420 | ||
421 | ||
422 | /* Thread-safe info field */ | |
423 | #if !__OBJC2__ | |
424 | OBJC_EXPORT void _class_setInfo(Class cls, long set); | |
425 | OBJC_EXPORT void _class_clearInfo(Class cls, long clear); | |
426 | OBJC_EXPORT void _class_changeInfo(Class cls, long set, long clear); | |
427 | #endif | |
428 | ||
429 | /* Secure /tmp usage */ | |
430 | OBJC_EXPORT int secure_open(const char *filename, int flags, uid_t euid); | |
13d88034 | 431 | |
13d88034 A |
432 | |
433 | #if !defined(SEG_OBJC) | |
434 | #define SEG_OBJC "__OBJC" /* objective-C runtime segment */ | |
435 | #endif | |
b3962a83 A |
436 | #if !defined(SEG_OBJC2) |
437 | #define SEG_OBJC2 "__OBJC2" | |
438 | #endif | |
13d88034 | 439 | |
13d88034 | 440 | |
2bfd4448 A |
441 | // Settings from environment variables |
442 | OBJC_EXPORT int PrintImages; // env OBJC_PRINT_IMAGES | |
443 | OBJC_EXPORT int PrintLoading; // env OBJC_PRINT_LOAD_METHODS | |
b3962a83 A |
444 | OBJC_EXPORT int PrintInitializing; // env OBJC_PRINT_INITIALIZE_METHODS |
445 | OBJC_EXPORT int PrintResolving; // env OBJC_PRINT_RESOLVED_METHODS | |
446 | OBJC_EXPORT int PrintConnecting; // env OBJC_PRINT_CLASS_SETUP | |
447 | OBJC_EXPORT int PrintProtocols; // env OBJC_PRINT_PROTOCOL_SETUP | |
448 | OBJC_EXPORT int PrintIvars; // env OBJC_PRINT_IVAR_SETUP | |
449 | OBJC_EXPORT int PrintFuture; // env OBJC_PRINT_FUTURE_CLASSES | |
2bfd4448 A |
450 | OBJC_EXPORT int PrintRTP; // env OBJC_PRINT_RTP |
451 | OBJC_EXPORT int PrintGC; // env OBJC_PRINT_GC | |
452 | OBJC_EXPORT int PrintSharing; // env OBJC_PRINT_SHARING | |
453 | OBJC_EXPORT int PrintCxxCtors; // env OBJC_PRINT_CXX_CTORS | |
b3962a83 A |
454 | OBJC_EXPORT int PrintExceptions; // env OBJC_PRINT_EXCEPTIONS |
455 | OBJC_EXPORT int PrintAltHandlers; // env OBJC_PRINT_ALT_HANDLERS | |
456 | OBJC_EXPORT int PrintDeprecation;// env OBJC_PRINT_DEPRECATION_WARNINGS | |
457 | OBJC_EXPORT int PrintReplacedMethods; // env OBJC_PRINT_REPLACED_METHODS | |
458 | OBJC_EXPORT int PrintCacheCollection; // env OBJC_PRINT_CACHE_COLLECTION | |
2bfd4448 A |
459 | OBJC_EXPORT int UseInternalZone; // env OBJC_USE_INTERNAL_ZONE |
460 | OBJC_EXPORT int AllowInterposing;// env OBJC_ALLOW_INTERPOSING | |
13d88034 | 461 | |
2bfd4448 A |
462 | OBJC_EXPORT int DebugUnload; // env OBJC_DEBUG_UNLOAD |
463 | OBJC_EXPORT int DebugFragileSuperclasses; // env OBJC_DEBUG_FRAGILE_SUPERCLASSES | |
b3962a83 A |
464 | OBJC_EXPORT int DebugFinalizers; // env OBJC_DEBUG_FINALIZERS |
465 | OBJC_EXPORT int DebugNilSync; // env OBJC_DEBUG_NIL_SYNC | |
2bfd4448 | 466 | |
b3962a83 | 467 | OBJC_EXPORT int DisableGC; // env OBJC_DISABLE_GC |
2bfd4448 | 468 | |
b3962a83 | 469 | /* GC state */ |
2bfd4448 | 470 | OBJC_EXPORT BOOL UseGC; // equivalent to calling objc_collecting_enabled() |
b3962a83 | 471 | OBJC_EXPORT auto_zone_t *gc_zone; // the GC zone, or NULL if no GC |
13d88034 | 472 | |
b3962a83 A |
473 | static __inline__ int _objc_strcmp(const char *s1, const char *s2) { |
474 | char c1, c2; | |
390d5862 A |
475 | for ( ; (c1 = *s1) == (c2 = *s2); s1++, s2++) |
476 | if (c1 == '\0') | |
477 | return 0; | |
478 | return (c1 - c2); | |
13d88034 A |
479 | } |
480 | ||
b3962a83 A |
481 | static __inline__ uintptr_t _objc_strhash(const char *s) { |
482 | uintptr_t hash = 0; | |
13d88034 A |
483 | for (;;) { |
484 | int a = *s++; | |
485 | if (0 == a) break; | |
486 | hash += (hash << 8) + a; | |
487 | } | |
488 | return hash; | |
489 | } | |
490 | ||
1f20c7a7 A |
491 | |
492 | // objc per-thread storage | |
1f20c7a7 A |
493 | typedef struct { |
494 | struct _objc_initializing_classes *initializingClasses; // for +initialize | |
b3962a83 A |
495 | struct _objc_lock_list *lockList; // for lock debugging |
496 | struct SyncCache *syncCache; // for @synchronize | |
497 | struct alt_handler_list *handlerList; // for exception alt handlers | |
1f20c7a7 A |
498 | |
499 | // If you add new fields here, don't forget to update | |
500 | // _objc_pthread_destroyspecific() | |
501 | ||
502 | } _objc_pthread_data; | |
503 | ||
b3962a83 A |
504 | OBJC_EXPORT _objc_pthread_data *_objc_fetch_pthread_data(BOOL create); |
505 | ||
1f20c7a7 A |
506 | |
507 | // Class state | |
b3962a83 A |
508 | #if !__OBJC2__ |
509 | #define ISCLASS(cls) (((cls)->info & CLS_CLASS) != 0) | |
510 | #define ISMETA(cls) (((cls)->info & CLS_META) != 0) | |
511 | #define GETMETA(cls) (ISMETA(cls) ? (cls) : (cls)->isa) | |
512 | #endif | |
1f20c7a7 A |
513 | |
514 | ||
2bfd4448 A |
515 | // Attribute for global variables to keep them out of bss storage |
516 | // To save one page per non-Objective-C process, variables used in | |
517 | // the "Objective-C not used" case should not be in bss storage. | |
518 | // On Tiger, this reduces the number of touched pages for each | |
519 | // CoreFoundation-only process from three to two. See #3857126 and #3857136. | |
520 | #define NOBSS __attribute__((section("__DATA,__data"))) | |
521 | ||
b3962a83 A |
522 | // cache.h |
523 | extern void flush_caches(Class cls, BOOL flush_meta); | |
524 | extern void flush_cache(Class cls); | |
525 | extern BOOL _cache_fill(Class cls, Method smt, SEL sel); | |
526 | extern void _cache_addForwardEntry(Class cls, SEL sel); | |
527 | extern void _cache_free(Cache cache); | |
528 | #if !__OBJC2__ | |
529 | // used by flush_caches outside objc-cache.m | |
530 | extern void _cache_flush(Class cls); | |
531 | extern pthread_mutex_t cacheUpdateLock; | |
532 | #ifdef OBJC_INSTRUMENTED | |
533 | extern unsigned int LinearFlushCachesCount; | |
534 | extern unsigned int LinearFlushCachesVisitedCount; | |
535 | extern unsigned int MaxLinearFlushCachesVisitedCount; | |
536 | extern unsigned int NonlinearFlushCachesCount; | |
537 | extern unsigned int NonlinearFlushCachesClassCount; | |
538 | extern unsigned int NonlinearFlushCachesVisitedCount; | |
539 | extern unsigned int MaxNonlinearFlushCachesVisitedCount; | |
540 | extern unsigned int IdealFlushCachesCount; | |
541 | extern unsigned int MaxIdealFlushCachesCount; | |
542 | #endif | |
543 | #endif | |
544 | ||
545 | // encoding.h | |
546 | extern unsigned int encoding_getNumberOfArguments(const char *typedesc); | |
547 | extern unsigned int encoding_getSizeOfArguments(const char *typedesc); | |
548 | extern unsigned int encoding_getArgumentInfo(const char *typedesc, int arg, const char **type, int *offset); | |
549 | extern void encoding_getReturnType(const char *t, char *dst, size_t dst_len); | |
550 | extern char * encoding_copyReturnType(const char *t); | |
551 | extern void encoding_getArgumentType(const char *t, unsigned int index, char *dst, size_t dst_len); | |
552 | extern char *encoding_copyArgumentType(const char *t, unsigned int index); | |
553 | ||
554 | // lock.h | |
555 | extern void _lock_debug(mutex_t lock, const char *name); | |
556 | extern void _checklock_debug(mutex_t lock, const char *name); | |
557 | extern void _checkunlock_debug(mutex_t lock, const char *name); | |
558 | extern void _unlock_debug(mutex_t lock, const char *name); | |
559 | extern void _destroyLockList(struct _objc_lock_list *locks); | |
560 | ||
561 | // sync.h | |
562 | extern void _destroySyncCache(struct SyncCache *cache); | |
563 | ||
564 | // layout.h | |
565 | typedef struct { | |
566 | uint8_t *bits; | |
567 | size_t bitCount; | |
568 | size_t bitsAllocated; | |
569 | BOOL weak; | |
570 | } layout_bitmap; | |
571 | extern layout_bitmap layout_bitmap_create(const unsigned char *layout_string, size_t layoutStringInstanceSize, size_t instanceSize, BOOL weak); | |
572 | extern void layout_bitmap_free(layout_bitmap bits); | |
573 | extern const unsigned char *layout_string_create(layout_bitmap bits); | |
574 | extern void layout_bitmap_set_ivar(layout_bitmap bits, const char *type, size_t offset); | |
575 | extern void layout_bitmap_grow(layout_bitmap *bits, size_t newCount); | |
576 | extern void layout_bitmap_slide(layout_bitmap *bits, size_t oldPos, size_t newPos); | |
577 | extern BOOL layout_bitmap_splat(layout_bitmap dst, layout_bitmap src, | |
578 | size_t oldSrcInstanceSize); | |
7c0e6487 A |
579 | extern BOOL layout_bitmap_or(layout_bitmap dst, layout_bitmap src, const char *msg); |
580 | ||
b3962a83 A |
581 | |
582 | // fixme runtime | |
583 | extern id look_up_class(const char *aClassName, BOOL includeUnconnected, BOOL includeClassHandler); | |
584 | extern void _read_images(header_info **hList, uint32_t hCount); | |
585 | extern void prepare_load_methods(header_info *hi); | |
586 | extern void _unload_image(header_info *hi); | |
587 | extern const char ** _objc_copyClassNamesForImage(header_info *hi, unsigned int *outCount); | |
588 | ||
589 | extern Class _objc_allocateFutureClass(const char *name); | |
590 | ||
591 | ||
592 | extern Property *copyPropertyList(struct objc_property_list *plist, unsigned int *outCount); | |
593 | ||
594 | ||
595 | extern const header_info *_headerForClass(Class cls); | |
596 | ||
597 | // fixme class | |
598 | extern Property property_list_nth(const struct objc_property_list *plist, uint32_t i); | |
599 | extern size_t property_list_size(const struct objc_property_list *plist); | |
600 | ||
601 | extern Class _class_getSuperclass(Class cls); | |
602 | extern BOOL _class_getInfo(Class cls, int info); | |
603 | extern const char *_class_getName(Class cls); | |
604 | extern size_t _class_getInstanceSize(Class cls); | |
605 | extern Class _class_getMeta(Class cls); | |
606 | extern BOOL _class_isMetaClass(Class cls); | |
607 | extern Cache _class_getCache(Class cls); | |
608 | extern void _class_setCache(Class cls, Cache cache); | |
609 | extern BOOL _class_isInitializing(Class cls); | |
610 | extern BOOL _class_isInitialized(Class cls); | |
611 | extern void _class_setInitializing(Class cls); | |
612 | extern void _class_setInitialized(Class cls); | |
613 | extern Class _class_getNonMetaClass(Class cls); | |
614 | extern Method _class_getMethodNoSuper(Class cls, SEL sel); | |
615 | extern Method _class_getMethod(Class cls, SEL sel); | |
616 | extern BOOL _class_isLoadable(Class cls); | |
617 | extern IMP _class_getLoadMethod(Class cls); | |
618 | extern BOOL _class_hasLoadMethod(Class cls); | |
619 | extern BOOL _class_hasCxxStructorsNoSuper(Class cls); | |
620 | extern BOOL _class_shouldFinalizeOnMainThread(Class cls); | |
621 | extern void _class_setFinalizeOnMainThread(Class cls); | |
622 | extern BOOL _class_shouldGrowCache(Class cls); | |
623 | extern void _class_setGrowCache(Class cls, BOOL grow); | |
624 | extern Ivar _class_getVariable(Class cls, const char *name); | |
625 | extern Class _class_getFreedObjectClass(void); | |
626 | extern Class _class_getNonexistentObjectClass(void); | |
627 | extern id _internal_class_createInstanceFromZone(Class cls, size_t extraBytes, | |
628 | void *zone); | |
629 | extern id _internal_object_dispose(id anObject); | |
630 | ||
631 | ||
632 | extern const char *_category_getName(Category cat); | |
633 | extern const char *_category_getClassName(Category cat); | |
634 | extern Class _category_getClass(Category cat); | |
635 | extern IMP _category_getLoadMethod(Category cat); | |
636 | ||
637 | #if !__OBJC2__ | |
638 | #define oldcls(cls) ((struct old_class *)cls) | |
639 | #define oldprotocol(proto) ((struct old_protocol *)proto) | |
640 | #define oldmethod(meth) ((struct old_method *)meth) | |
641 | #define oldcategory(cat) ((struct old_category *)cat) | |
642 | #define oldivar(ivar) ((struct old_ivar *)ivar) | |
643 | ||
644 | static inline struct old_method *_method_asOld(Method m) { return (struct old_method *)m; } | |
645 | static inline struct old_class *_class_asOld(Class cls) { return (struct old_class *)cls; } | |
646 | static inline struct old_category *_category_asOld(Category cat) { return (struct old_category *)cat; } | |
647 | ||
648 | extern void unload_class(struct old_class *cls); | |
649 | #endif | |
650 | ||
651 | extern BOOL object_cxxConstruct(id obj); | |
652 | extern void object_cxxDestruct(id obj); | |
653 | ||
654 | #if !__OBJC2__ | |
655 | #define CLS_CLASS 0x1 | |
656 | #define CLS_META 0x2 | |
657 | #define CLS_INITIALIZED 0x4 | |
658 | #define CLS_POSING 0x8 | |
659 | #define CLS_MAPPED 0x10 | |
660 | #define CLS_FLUSH_CACHE 0x20 | |
661 | #define CLS_GROW_CACHE 0x40 | |
662 | #define CLS_NEED_BIND 0x80 | |
663 | #define CLS_METHOD_ARRAY 0x100 | |
664 | // the JavaBridge constructs classes with these markers | |
665 | #define CLS_JAVA_HYBRID 0x200 | |
666 | #define CLS_JAVA_CLASS 0x400 | |
667 | // thread-safe +initialize | |
668 | #define CLS_INITIALIZING 0x800 | |
669 | // bundle unloading | |
670 | #define CLS_FROM_BUNDLE 0x1000 | |
671 | // C++ ivar support | |
672 | #define CLS_HAS_CXX_STRUCTORS 0x2000 | |
673 | // Lazy method list arrays | |
674 | #define CLS_NO_METHOD_ARRAY 0x4000 | |
675 | // +load implementation | |
676 | #define CLS_HAS_LOAD_METHOD 0x8000 | |
677 | // objc_allocateClassPair API | |
678 | #define CLS_CONSTRUCTING 0x10000 | |
679 | // visibility=hidden | |
680 | #define CLS_HIDDEN 0x20000 | |
681 | // GC: class has unsafe finalize method | |
682 | #define CLS_FINALIZE_ON_MAIN_THREAD 0x40000 | |
683 | // Lazy property list arrays | |
684 | #define CLS_NO_PROPERTY_ARRAY 0x80000 | |
cacad474 | 685 | // +load implementation |
b3962a83 A |
686 | #define CLS_CONNECTED 0x100000 |
687 | #define CLS_LOADED 0x200000 | |
688 | // objc_allocateClassPair API | |
689 | #define CLS_CONSTRUCTED 0x400000 | |
690 | // class is leaf for cache flushing | |
691 | #define CLS_LEAF 0x800000 | |
692 | #endif | |
693 | ||
694 | #define OBJC_WARN_DEPRECATED \ | |
695 | do { \ | |
696 | static int warned = 0; \ | |
697 | if (!warned) { \ | |
698 | warned = 1; \ | |
699 | _objc_warn_deprecated(__FUNCTION__, NULL); \ | |
700 | } \ | |
701 | } while (0) \ | |
702 | ||
703 | /* Method prototypes */ | |
704 | @interface DoesNotExist | |
705 | + class; | |
706 | + initialize; | |
707 | - (id)description; | |
708 | - (const char *)UTF8String; | |
709 | - (unsigned long)hash; | |
710 | - (BOOL)isEqual:(id)object; | |
711 | - free; | |
712 | @end | |
cacad474 | 713 | |
13d88034 A |
714 | #endif /* _OBJC_PRIVATE_H_ */ |
715 |