ObjFW
private.h
1 /*
2  * Copyright (c) 2008-2021 Jonathan Schleifer <js@nil.im>
3  *
4  * All rights reserved.
5  *
6  * This file is part of ObjFW. It may be distributed under the terms of the
7  * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
8  * the packaging of this file.
9  *
10  * Alternatively, it may be distributed under the terms of the GNU General
11  * Public License, either version 2 or 3, which can be found in the file
12  * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
13  * file.
14  */
15 
16 #include "config.h"
17 
18 #import "macros.h"
19 #import "platform.h"
20 
21 #if !defined(__has_feature) || !__has_feature(nullability)
22 # ifndef _Nonnull
23 # define _Nonnull
24 # endif
25 # ifndef _Nullable
26 # define _Nullable
27 # endif
28 #endif
29 
30 typedef uint32_t (*_Nonnull objc_hashtable_hash_func)(const void *_Nonnull key);
31 typedef bool (*_Nonnull objc_hashtable_equal_func)(const void *_Nonnull key1,
32  const void *_Nonnull key2);
33 
34 struct objc_class {
35  Class _Nonnull isa;
36  Class _Nullable superclass;
37  const char *_Nonnull name;
38  unsigned long version;
39  unsigned long info;
40  long instanceSize;
41  struct objc_ivar_list *_Nullable ivars;
42  struct objc_method_list *_Nullable methodList;
43  struct objc_dtable *_Nonnull DTable;
44  Class _Nullable *_Nullable subclassList;
45  void *_Nullable siblingClass;
46  struct objc_protocol_list *_Nullable protocols;
47  void *_Nullable GCObjectType;
48  unsigned long ABIVersion;
49  int32_t *_Nonnull *_Nullable ivarOffsets;
50  struct objc_property_list *_Nullable propertyList;
51 };
52 
53 enum objc_class_info {
54  OBJC_CLASS_INFO_CLASS = 0x001,
55  OBJC_CLASS_INFO_METACLASS = 0x002,
56  OBJC_CLASS_INFO_NEW_ABI = 0x010,
57  OBJC_CLASS_INFO_SETUP = 0x100,
58  OBJC_CLASS_INFO_LOADED = 0x200,
59  OBJC_CLASS_INFO_DTABLE = 0x400,
60  OBJC_CLASS_INFO_INITIALIZED = 0x800
61 };
62 
63 struct objc_object {
64  Class _Nonnull isa;
65 };
66 
67 struct objc_selector {
68  uintptr_t UID;
69  const char *_Nullable typeEncoding;
70 };
71 
72 struct objc_method {
73  struct objc_selector selector;
74  IMP _Nonnull implementation;
75 };
76 
77 struct objc_method_list {
78  struct objc_method_list *_Nullable next;
79  unsigned int count;
80  struct objc_method methods[1];
81 };
82 
83 struct objc_category {
84  const char *_Nonnull categoryName;
85  const char *_Nonnull className;
86  struct objc_method_list *_Nullable instanceMethods;
87  struct objc_method_list *_Nullable classMethods;
88  struct objc_protocol_list *_Nullable protocols;
89 };
90 
91 struct objc_ivar {
92  const char *_Nonnull name;
93  const char *_Nonnull typeEncoding;
94  unsigned int offset;
95 };
96 
97 struct objc_ivar_list {
98  unsigned int count;
99  struct objc_ivar ivars[1];
100 };
101 
102 struct objc_method_description {
103  const char *_Nonnull name;
104  const char *_Nonnull typeEncoding;
105 };
106 
107 struct objc_method_description_list {
108  int count;
109  struct objc_method_description list[1];
110 };
111 
112 struct objc_protocol_list {
113  struct objc_protocol_list *_Nullable next;
114  long count;
115  Protocol *__unsafe_unretained _Nonnull list[1];
116 };
117 
118 #if __has_attribute(__objc_root_class__)
119 __attribute__((__objc_root_class__))
120 #endif
121 @interface Protocol
122 {
123 @public
124  Class _Nonnull isa;
125  const char *_Nonnull name;
126  struct objc_protocol_list *_Nullable protocolList;
127  struct objc_method_description_list *_Nullable instanceMethods;
128  struct objc_method_description_list *_Nullable classMethods;
129 }
130 @end
131 
132 enum objc_property_attributes {
133  OBJC_PROPERTY_READONLY = 0x01,
134  OBJC_PROPERTY_GETTER = 0x02,
135  OBJC_PROPERTY_ASSIGN = 0x04,
136  OBJC_PROPERTY_READWRITE = 0x08,
137  OBJC_PROPERTY_RETAIN = 0x10,
138  OBJC_PROPERTY_COPY = 0x20,
139  OBJC_PROPERTY_NONATOMIC = 0x40,
140  OBJC_PROPERTY_SETTER = 0x80
141 };
142 
143 enum objc_property_extended_attributes {
144  OBJC_PROPERTY_SYNTHESIZED = 0x1,
145  OBJC_PROPERTY_DYNAMIC = 0x2,
146  OBJC_PROPERTY_PROTOCOL = 0x3,
147  OBJC_PROPERTY_ATOMIC = 0x4,
148  OBJC_PROPERTY_WEAK = 0x8,
149  OBJC_PROPERTY_STRONG = 0x10,
150  OBJC_PROPERTY_UNSAFE_UNRETAINED = 0x20
151 };
152 
153 struct objc_property {
154  const char *_Nonnull name;
155  unsigned char attributes, extendedAttributes;
156  struct {
157  const char *_Nullable name;
158  const char *_Nullable typeEncoding;
159  } getter, setter;
160 };
161 
162 struct objc_property_list {
163  unsigned int count;
164  struct objc_property_list *_Nullable next;
165  struct objc_property properties[1];
166 };
167 
168 struct objc_static_instances {
169  const char *_Nonnull className;
170  id _Nullable instances[1];
171 };
172 
173 struct objc_symtab {
174  unsigned long unknown;
175  struct objc_selector *_Nullable selectorRefs;
176  uint16_t classDefsCount;
177  uint16_t categoryDefsCount;
178  void *_Nonnull defs[1];
179 };
180 
181 struct objc_module {
182  unsigned long version; /* 9 = non-fragile */
183  unsigned long size;
184  const char *_Nullable name;
185  struct objc_symtab *_Nonnull symtab;
186 };
187 
188 struct objc_hashtable_bucket {
189  const void *_Nonnull key, *_Nonnull object;
190  uint32_t hash;
191 };
192 
193 struct objc_hashtable {
194  objc_hashtable_hash_func hash;
195  objc_hashtable_equal_func equal;
196  uint32_t count, size;
197  struct objc_hashtable_bucket *_Nonnull *_Nullable data;
198 };
199 
200 struct objc_sparsearray {
201  struct objc_sparsearray_data {
202  void *_Nullable next[256];
203  } *_Nonnull data;
204  uint8_t indexSize;
205 };
206 
207 struct objc_dtable {
208  struct objc_dtable_level2 {
209 #ifdef OF_SELUID24
210  struct objc_dtable_level3 {
211  IMP _Nullable buckets[256];
212  } *_Nonnull buckets[256];
213 #else
214  IMP _Nullable buckets[256];
215 #endif
216  } *_Nonnull buckets[256];
217 };
218 
219 #if defined(OBJC_COMPILING_AMIGA_LIBRARY) || \
220  defined(OBJC_COMPILING_AMIGA_LINKLIB)
221 struct objc_libc {
222  void *_Nullable (*_Nonnull malloc)(size_t);
223  void *_Nullable (*_Nonnull calloc)(size_t, size_t);
224  void *_Nullable (*_Nonnull realloc)(void *_Nullable, size_t);
225  void (*_Nonnull free)(void *_Nullable);
226 # ifdef HAVE_SJLJ_EXCEPTIONS
227  int (*_Nonnull _Unwind_SjLj_RaiseException)(void *_Nonnull);
228 # else
229  int (*_Nonnull _Unwind_RaiseException)(void *_Nonnull);
230 # endif
231  void (*_Nonnull _Unwind_DeleteException)(void *_Nonnull);
232  void *_Nullable (*_Nonnull _Unwind_GetLanguageSpecificData)(
233  void *_Nonnull);
234  uintptr_t (*_Nonnull _Unwind_GetRegionStart)(void *_Nonnull);
235  uintptr_t (*_Nonnull _Unwind_GetDataRelBase)(void *_Nonnull);
236  uintptr_t (*_Nonnull _Unwind_GetTextRelBase)(void *_Nonnull);
237  uintptr_t (*_Nonnull _Unwind_GetIP)(void *_Nonnull);
238  uintptr_t (*_Nonnull _Unwind_GetGR)(void *_Nonnull, int);
239  void (*_Nonnull _Unwind_SetIP)(void *_Nonnull, uintptr_t);
240  void (*_Nonnull _Unwind_SetGR)(void *_Nonnull, int, uintptr_t);
241 # ifdef HAVE_SJLJ_EXCEPTIONS
242  void (*_Nonnull _Unwind_SjLj_Resume)(void *_Nonnull);
243 # else
244  void (*_Nonnull _Unwind_Resume)(void *_Nonnull);
245 # endif
246 # ifdef OF_AMIGAOS_M68K
247  void (*_Nonnull __register_frame_info)(const void *_Nonnull,
248  void *_Nonnull);
249  void *(*_Nonnull __deregister_frame_info)(const void *_Nonnull);
250 # endif
251 # ifdef OF_MORPHOS
252  void (*_Nonnull __register_frame)(void *_Nonnull);
253  void (*_Nonnull __deregister_frame)(void *_Nonnull);
254 # endif
255 # ifdef OF_AMIGAOS_M68K
256  int (*_Nonnull vsnprintf)(char *restrict _Nonnull str, size_t size,
257  const char *_Nonnull restrict fmt, va_list args);
258 # endif
259  int (*_Nonnull atexit)(void (*_Nonnull)(void));
260  void (*_Nonnull exit)(int);
261 };
262 #endif
263 
264 #ifdef OBJC_COMPILING_AMIGA_LIBRARY
265 # if defined(__MORPHOS__)
266 # include <ppcinline/macros.h>
267 # define OBJC_M68K_ARG(type, name, reg) type name = (type)REG_##reg;
268 # else
269 # define OBJC_M68K_ARG(type, name, reg) \
270  register type reg_##name __asm__(#reg); \
271  type name = reg_##name;
272 # endif
273 
274 extern bool objc_init(unsigned int, struct objc_libc *);
275 # ifdef HAVE_SJLJ_EXCEPTIONS
276 # define __gnu_objc_personality(version, actions, exClass, ex, ctx) \
277  __gnu_objc_personality_sj0(version, actions, *exClass, ex, ctx)
278 # else
279 # define __gnu_objc_personality(version, actions, exClass, ex, ctx) \
280  __gnu_objc_personality_v0(version, actions, *exClass, ex, ctx)
281 # endif
282 #endif
283 
284 extern void objc_register_all_categories(struct objc_symtab *_Nonnull);
285 extern struct objc_category *_Nullable *_Nullable
286  objc_categories_for_class(Class _Nonnull);
287 extern void objc_unregister_all_categories(void);
288 extern void objc_initialize_class(Class _Nonnull);
289 extern void objc_update_dtable(Class _Nonnull);
290 extern void objc_register_all_classes(struct objc_symtab *_Nonnull);
291 extern Class _Nullable objc_classname_to_class(const char *_Nonnull, bool);
292 extern void objc_unregister_class(Class _Nonnull);
293 extern void objc_unregister_all_classes(void);
294 extern uint32_t objc_hash_string(const void *_Nonnull);
295 extern bool objc_equal_string(const void *_Nonnull, const void *_Nonnull);
296 extern struct objc_hashtable *_Nonnull objc_hashtable_new(
297  objc_hashtable_hash_func, objc_hashtable_equal_func, uint32_t);
298 extern struct objc_hashtable_bucket objc_deleted_bucket;
299 extern void objc_hashtable_set(struct objc_hashtable *_Nonnull,
300  const void *_Nonnull, const void *_Nonnull);
301 extern void *_Nullable objc_hashtable_get(struct objc_hashtable *_Nonnull,
302  const void *_Nonnull);
303 extern void objc_hashtable_delete(struct objc_hashtable *_Nonnull,
304  const void *_Nonnull);
305 extern void objc_hashtable_free(struct objc_hashtable *_Nonnull);
306 extern void objc_register_selector(struct objc_selector *_Nonnull);
307 extern void objc_register_all_selectors(struct objc_symtab *_Nonnull);
308 extern void objc_unregister_all_selectors(void);
309 extern struct objc_sparsearray *_Nonnull objc_sparsearray_new(uint8_t);
310 extern void *_Nullable objc_sparsearray_get(struct objc_sparsearray *_Nonnull,
311  uintptr_t);
312 extern void objc_sparsearray_set(struct objc_sparsearray *_Nonnull, uintptr_t,
313  void *_Nullable);
314 extern void objc_sparsearray_free(struct objc_sparsearray *_Nonnull);
315 extern struct objc_dtable *_Nonnull objc_dtable_new(void);
316 extern void objc_dtable_copy(struct objc_dtable *_Nonnull,
317  struct objc_dtable *_Nonnull);
318 extern void objc_dtable_set(struct objc_dtable *_Nonnull, uint32_t,
319  IMP _Nullable);
320 extern void objc_dtable_free(struct objc_dtable *_Nonnull);
321 extern void objc_dtable_cleanup(void);
322 extern void objc_init_static_instances(struct objc_symtab *_Nonnull);
323 extern void objc_forget_pending_static_instances(void);
324 extern void objc_zero_weak_references(id _Nonnull);
325 extern Class _Nullable object_getTaggedPointerClass(id _Nonnull);
326 #ifdef OF_HAVE_THREADS
327 extern void objc_global_mutex_lock(void);
328 extern void objc_global_mutex_unlock(void);
329 extern void objc_global_mutex_free(void);
330 #else
331 # define objc_global_mutex_lock()
332 # define objc_global_mutex_unlock()
333 # define objc_global_mutex_free()
334 #endif
335 
336 static inline IMP _Nullable
337 objc_dtable_get(const struct objc_dtable *_Nonnull dtable, uint32_t idx)
338 {
339 #ifdef OF_SELUID24
340  uint8_t i = idx >> 16;
341  uint8_t j = idx >> 8;
342  uint8_t k = idx;
343 
344  return dtable->buckets[i]->buckets[j]->buckets[k];
345 #else
346  uint8_t i = idx >> 8;
347  uint8_t j = idx;
348 
349  return dtable->buckets[i]->buckets[j];
350 #endif
351 }
352 
353 extern void OF_NO_RETURN_FUNC objc_error(const char *_Nonnull title,
354  const char *_Nonnull format, ...);
355 #define OBJC_ERROR(...) \
356  objc_error("ObjFWRT @ " __FILE__ ":" OF_STRINGIFY(__LINE__), \
357  __VA_ARGS__)
358 
359 #if defined(OF_ELF)
360 # if defined(OF_X86_64) || defined(OF_X86) || defined(OF_POWERPC) || \
361  defined(OF_ARM64) || defined(OF_ARM) || \
362  defined(OF_MIPS64_N64) || defined(OF_MIPS) || \
363  defined(OF_SPARC64) || defined(OF_SPARC)
364 # define OF_ASM_LOOKUP
365 # endif
366 #elif defined(OF_MACH_O)
367 # if defined(OF_X86_64)
368 # define OF_ASM_LOOKUP
369 # endif
370 #elif defined(OF_WINDOWS)
371 # if defined(OF_X86_64) || defined(OF_X86)
372 # define OF_ASM_LOOKUP
373 # endif
374 #endif
375 
376 @interface DummyObject
377 {
378  Class _Nonnull isa;
379 }
380 
381 @property (readonly, nonatomic) bool allowsWeakReference;
382 
383 + (void)initialize;
384 + (bool)resolveClassMethod: (nonnull SEL)selector;
385 + (bool)resolveInstanceMethod: (nonnull SEL)selector;
386 - (nonnull id)retain;
387 - (void)release;
388 - (nonnull id)autorelease;
389 - (nonnull id)copy;
390 - (nonnull id)mutableCopy;
391 - (bool)retainWeakReference;
392 @end
struct objc_object * id
A pointer to any object.
Definition: ObjFWRT.h:90
id _Nullable(* IMP)(id _Nonnull object, SEL _Nonnull selector,...)
A method implemenation.
Definition: ObjFWRT.h:142
struct objc_class * Class
A pointer to a class.
Definition: ObjFWRT.h:85
const struct objc_protocol * Protocol
A protocol.
Definition: ObjFWRT.h:113