objc-private.h 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979
  1. /*
  2. * Copyright (c) 1999-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. * objc-private.h
  25. * Copyright 1988-1996, NeXT Software, Inc.
  26. */
  27. #ifndef _OBJC_PRIVATE_H_
  28. #define _OBJC_PRIVATE_H_
  29. #include "objc-config.h"
  30. /* Isolate ourselves from the definitions of id and Class in the compiler
  31. * and public headers.
  32. */
  33. #ifdef _OBJC_OBJC_H_
  34. #error include objc-private.h before other headers
  35. #endif
  36. #define OBJC_TYPES_DEFINED 1
  37. #undef OBJC_OLD_DISPATCH_PROTOTYPES
  38. #define OBJC_OLD_DISPATCH_PROTOTYPES 0
  39. #include <cstddef> // for nullptr_t
  40. #include <stdint.h>
  41. #include <assert.h>
  42. struct objc_class;
  43. struct objc_object;
  44. typedef struct objc_class *Class;
  45. typedef struct objc_object *id;
  46. namespace {
  47. struct SideTable;
  48. };
  49. #include "isa.h"
  50. union isa_t {
  51. isa_t() { }
  52. isa_t(uintptr_t value) : bits(value) { }
  53. Class cls;
  54. uintptr_t bits;
  55. #if defined(ISA_BITFIELD)
  56. struct {
  57. ISA_BITFIELD; // defined in isa.h
  58. };
  59. #endif
  60. };
  61. struct objc_object {
  62. private:
  63. isa_t isa;
  64. public:
  65. // ISA() assumes this is NOT a tagged pointer object
  66. Class ISA();
  67. // getIsa() allows this to be a tagged pointer object
  68. Class getIsa();
  69. // initIsa() should be used to init the isa of new objects only.
  70. // If this object already has an isa, use changeIsa() for correctness.
  71. // initInstanceIsa(): objects with no custom RR/AWZ
  72. // initClassIsa(): class objects
  73. // initProtocolIsa(): protocol objects
  74. // initIsa(): other objects
  75. void initIsa(Class cls /*nonpointer=false*/);
  76. void initClassIsa(Class cls /*nonpointer=maybe*/);
  77. void initProtocolIsa(Class cls /*nonpointer=maybe*/);
  78. void initInstanceIsa(Class cls, bool hasCxxDtor);
  79. // changeIsa() should be used to change the isa of existing objects.
  80. // If this is a new object, use initIsa() for performance.
  81. Class changeIsa(Class newCls);
  82. bool hasNonpointerIsa();
  83. bool isTaggedPointer();
  84. bool isBasicTaggedPointer();
  85. bool isExtTaggedPointer();
  86. bool isClass();
  87. // object may have associated objects?
  88. bool hasAssociatedObjects();
  89. void setHasAssociatedObjects();
  90. // object may be weakly referenced?
  91. bool isWeaklyReferenced();
  92. void setWeaklyReferenced_nolock();
  93. // object may have -.cxx_destruct implementation?
  94. bool hasCxxDtor();
  95. // Optimized calls to retain/release methods
  96. id retain();
  97. void release();
  98. id autorelease();
  99. // Implementations of retain/release methods
  100. id rootRetain();
  101. bool rootRelease();
  102. id rootAutorelease();
  103. bool rootTryRetain();
  104. bool rootReleaseShouldDealloc();
  105. uintptr_t rootRetainCount();
  106. // Implementation of dealloc methods
  107. bool rootIsDeallocating();
  108. void clearDeallocating();
  109. void rootDealloc();
  110. private:
  111. void initIsa(Class newCls, bool nonpointer, bool hasCxxDtor);
  112. // Slow paths for inline control
  113. id rootAutorelease2();
  114. bool overrelease_error();
  115. #if SUPPORT_NONPOINTER_ISA
  116. // Unified retain count manipulation for nonpointer isa
  117. id rootRetain(bool tryRetain, bool handleOverflow);
  118. bool rootRelease(bool performDealloc, bool handleUnderflow);
  119. id rootRetain_overflow(bool tryRetain);
  120. bool rootRelease_underflow(bool performDealloc);
  121. void clearDeallocating_slow();
  122. // Side table retain count overflow for nonpointer isa
  123. void sidetable_lock();
  124. void sidetable_unlock();
  125. void sidetable_moveExtraRC_nolock(size_t extra_rc, bool isDeallocating, bool weaklyReferenced);
  126. bool sidetable_addExtraRC_nolock(size_t delta_rc);
  127. size_t sidetable_subExtraRC_nolock(size_t delta_rc);
  128. size_t sidetable_getExtraRC_nolock();
  129. #endif
  130. // Side-table-only retain count
  131. bool sidetable_isDeallocating();
  132. void sidetable_clearDeallocating();
  133. bool sidetable_isWeaklyReferenced();
  134. void sidetable_setWeaklyReferenced_nolock();
  135. id sidetable_retain();
  136. id sidetable_retain_slow(SideTable& table);
  137. uintptr_t sidetable_release(bool performDealloc = true);
  138. uintptr_t sidetable_release_slow(SideTable& table, bool performDealloc = true);
  139. bool sidetable_tryRetain();
  140. uintptr_t sidetable_retainCount();
  141. #if DEBUG
  142. bool sidetable_present();
  143. #endif
  144. };
  145. #if __OBJC2__
  146. typedef struct method_t *Method;
  147. typedef struct ivar_t *Ivar;
  148. typedef struct category_t *Category;
  149. typedef struct property_t *objc_property_t;
  150. #else
  151. typedef struct old_method *Method;
  152. typedef struct old_ivar *Ivar;
  153. typedef struct old_category *Category;
  154. typedef struct old_property *objc_property_t;
  155. #endif
  156. // Public headers
  157. #include "objc.h"
  158. #include "runtime.h"
  159. #include "objc-os.h"
  160. #include "objc-abi.h"
  161. #include "objc-api.h"
  162. #include "objc-config.h"
  163. #include "objc-internal.h"
  164. #include "maptable.h"
  165. #include "hashtable2.h"
  166. /* Do not include message.h here. */
  167. /* #include "message.h" */
  168. #define __APPLE_API_PRIVATE
  169. #include "objc-gdb.h"
  170. #undef __APPLE_API_PRIVATE
  171. // Private headers
  172. #include "objc-ptrauth.h"
  173. #if __OBJC2__
  174. #include "objc-runtime-new.h"
  175. #else
  176. #include "objc-runtime-old.h"
  177. #endif
  178. #include "objc-references.h"
  179. #include "objc-initialize.h"
  180. #include "objc-loadmethod.h"
  181. #if SUPPORT_PREOPT && __cplusplus
  182. #include <objc-shared-cache.h>
  183. using objc_selopt_t = const objc_opt::objc_selopt_t;
  184. #else
  185. struct objc_selopt_t;
  186. #endif
  187. #define STRINGIFY(x) #x
  188. #define STRINGIFY2(x) STRINGIFY(x)
  189. __BEGIN_DECLS
  190. struct header_info;
  191. // Split out the rw data from header info. For now put it in a huge array
  192. // that more than exceeds the space needed. In future we'll just allocate
  193. // this in the shared cache builder.
  194. typedef struct header_info_rw {
  195. bool getLoaded() const {
  196. return isLoaded;
  197. }
  198. void setLoaded(bool v) {
  199. isLoaded = v ? 1: 0;
  200. }
  201. bool getAllClassesRealized() const {
  202. return allClassesRealized;
  203. }
  204. void setAllClassesRealized(bool v) {
  205. allClassesRealized = v ? 1: 0;
  206. }
  207. header_info *getNext() const {
  208. return (header_info *)(next << 2);
  209. }
  210. void setNext(header_info *v) {
  211. next = ((uintptr_t)v) >> 2;
  212. }
  213. private:
  214. #ifdef __LP64__
  215. uintptr_t isLoaded : 1;
  216. uintptr_t allClassesRealized : 1;
  217. uintptr_t next : 62;
  218. #else
  219. uintptr_t isLoaded : 1;
  220. uintptr_t allClassesRealized : 1;
  221. uintptr_t next : 30;
  222. #endif
  223. } header_info_rw;
  224. struct header_info_rw* getPreoptimizedHeaderRW(const struct header_info *const hdr);
  225. typedef struct header_info {
  226. private:
  227. // Note, this is no longer a pointer, but instead an offset to a pointer
  228. // from this location.
  229. intptr_t mhdr_offset;
  230. // Note, this is no longer a pointer, but instead an offset to a pointer
  231. // from this location.
  232. intptr_t info_offset;
  233. // Do not add fields without editing ObjCModernAbstraction.hpp
  234. public:
  235. header_info_rw *getHeaderInfoRW() {
  236. header_info_rw *preopt =
  237. isPreoptimized() ? getPreoptimizedHeaderRW(this) : nil;
  238. if (preopt) return preopt;
  239. else return &rw_data[0];
  240. }
  241. const headerType *mhdr() const {
  242. return (const headerType *)(((intptr_t)&mhdr_offset) + mhdr_offset);
  243. }
  244. void setmhdr(const headerType *mhdr) {
  245. mhdr_offset = (intptr_t)mhdr - (intptr_t)&mhdr_offset;
  246. }
  247. const objc_image_info *info() const {
  248. return (const objc_image_info *)(((intptr_t)&info_offset) + info_offset);
  249. }
  250. void setinfo(const objc_image_info *info) {
  251. info_offset = (intptr_t)info - (intptr_t)&info_offset;
  252. }
  253. bool isLoaded() {
  254. return getHeaderInfoRW()->getLoaded();
  255. }
  256. void setLoaded(bool v) {
  257. getHeaderInfoRW()->setLoaded(v);
  258. }
  259. bool areAllClassesRealized() {
  260. return getHeaderInfoRW()->getAllClassesRealized();
  261. }
  262. void setAllClassesRealized(bool v) {
  263. getHeaderInfoRW()->setAllClassesRealized(v);
  264. }
  265. header_info *getNext() {
  266. return getHeaderInfoRW()->getNext();
  267. }
  268. void setNext(header_info *v) {
  269. getHeaderInfoRW()->setNext(v);
  270. }
  271. bool isBundle() {
  272. return mhdr()->filetype == MH_BUNDLE;
  273. }
  274. const char *fname() const {
  275. return dyld_image_path_containing_address(mhdr());
  276. }
  277. bool isPreoptimized() const;
  278. #if !__OBJC2__
  279. struct old_protocol **proto_refs;
  280. struct objc_module *mod_ptr;
  281. size_t mod_count;
  282. # if TARGET_OS_WIN32
  283. struct objc_module **modules;
  284. size_t moduleCount;
  285. struct old_protocol **protocols;
  286. size_t protocolCount;
  287. void *imageinfo;
  288. size_t imageinfoBytes;
  289. SEL *selrefs;
  290. size_t selrefCount;
  291. struct objc_class **clsrefs;
  292. size_t clsrefCount;
  293. TCHAR *moduleName;
  294. # endif
  295. #endif
  296. private:
  297. // Images in the shared cache will have an empty array here while those
  298. // allocated at run time will allocate a single entry.
  299. header_info_rw rw_data[];
  300. } header_info;
  301. extern header_info *FirstHeader;
  302. extern header_info *LastHeader;
  303. extern int HeaderCount;
  304. extern void appendHeader(header_info *hi);
  305. extern void removeHeader(header_info *hi);
  306. extern objc_image_info *_getObjcImageInfo(const headerType *head, size_t *size);
  307. extern bool _hasObjcContents(const header_info *hi);
  308. // Mach-O segment and section names are 16 bytes and may be un-terminated.
  309. static inline bool segnameEquals(const char *lhs, const char *rhs) {
  310. return 0 == strncmp(lhs, rhs, 16);
  311. }
  312. static inline bool segnameStartsWith(const char *segname, const char *prefix) {
  313. return 0 == strncmp(segname, prefix, strlen(prefix));
  314. }
  315. static inline bool sectnameEquals(const char *lhs, const char *rhs) {
  316. return segnameEquals(lhs, rhs);
  317. }
  318. static inline bool sectnameStartsWith(const char *sectname, const char *prefix){
  319. return segnameStartsWith(sectname, prefix);
  320. }
  321. /* selectors */
  322. extern void sel_init(size_t selrefCount);
  323. extern SEL sel_registerNameNoLock(const char *str, bool copy);
  324. extern SEL SEL_load;
  325. extern SEL SEL_initialize;
  326. extern SEL SEL_resolveClassMethod;
  327. extern SEL SEL_resolveInstanceMethod;
  328. extern SEL SEL_cxx_construct;
  329. extern SEL SEL_cxx_destruct;
  330. extern SEL SEL_retain;
  331. extern SEL SEL_release;
  332. extern SEL SEL_autorelease;
  333. extern SEL SEL_retainCount;
  334. extern SEL SEL_alloc;
  335. extern SEL SEL_allocWithZone;
  336. extern SEL SEL_dealloc;
  337. extern SEL SEL_copy;
  338. extern SEL SEL_new;
  339. extern SEL SEL_forwardInvocation;
  340. extern SEL SEL_tryRetain;
  341. extern SEL SEL_isDeallocating;
  342. extern SEL SEL_retainWeakReference;
  343. extern SEL SEL_allowsWeakReference;
  344. /* preoptimization */
  345. extern void preopt_init(void);
  346. extern void disableSharedCacheOptimizations(void);
  347. extern bool isPreoptimized(void);
  348. extern bool noMissingWeakSuperclasses(void);
  349. extern header_info *preoptimizedHinfoForHeader(const headerType *mhdr);
  350. extern objc_selopt_t *preoptimizedSelectors(void);
  351. extern Protocol *getPreoptimizedProtocol(const char *name);
  352. extern unsigned getPreoptimizedClassUnreasonableCount();
  353. extern Class getPreoptimizedClass(const char *name);
  354. extern Class* copyPreoptimizedClasses(const char *name, int *outCount);
  355. extern bool sharedRegionContains(const void *ptr);
  356. extern Class _calloc_class(size_t size);
  357. /* method lookup */
  358. extern IMP lookUpImpOrNil(Class, SEL, id obj, bool initialize, bool cache, bool resolver);
  359. extern IMP lookUpImpOrForward(Class, SEL, id obj, bool initialize, bool cache, bool resolver);
  360. extern IMP lookupMethodInClassAndLoadCache(Class cls, SEL sel);
  361. extern bool class_respondsToSelector_inst(Class cls, SEL sel, id inst);
  362. extern bool objcMsgLogEnabled;
  363. extern bool logMessageSend(bool isClassMethod,
  364. const char *objectsClass,
  365. const char *implementingClass,
  366. SEL selector);
  367. /* message dispatcher */
  368. extern IMP _class_lookupMethodAndLoadCache3(id, SEL, Class);
  369. #if !OBJC_OLD_DISPATCH_PROTOTYPES
  370. extern void _objc_msgForward_impcache(void);
  371. #else
  372. extern id _objc_msgForward_impcache(id, SEL, ...);
  373. #endif
  374. /* errors */
  375. extern void __objc_error(id, const char *, ...) __attribute__((format (printf, 2, 3), noreturn));
  376. extern void _objc_inform(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
  377. extern void _objc_inform_on_crash(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
  378. extern void _objc_inform_now_and_on_crash(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
  379. extern void _objc_inform_deprecated(const char *oldname, const char *newname) __attribute__((noinline));
  380. extern void inform_duplicate(const char *name, Class oldCls, Class cls);
  381. /* magic */
  382. extern Class _objc_getFreedObjectClass (void);
  383. /* map table additions */
  384. extern void *NXMapKeyCopyingInsert(NXMapTable *table, const void *key, const void *value);
  385. extern void *NXMapKeyFreeingRemove(NXMapTable *table, const void *key);
  386. /* hash table additions */
  387. extern unsigned _NXHashCapacity(NXHashTable *table);
  388. extern void _NXHashRehashToCapacity(NXHashTable *table, unsigned newCapacity);
  389. /* property attribute parsing */
  390. extern const char *copyPropertyAttributeString(const objc_property_attribute_t *attrs, unsigned int count);
  391. extern objc_property_attribute_t *copyPropertyAttributeList(const char *attrs, unsigned int *outCount);
  392. extern char *copyPropertyAttributeValue(const char *attrs, const char *name);
  393. /* locking */
  394. extern void lock_init(void);
  395. class monitor_locker_t : nocopy_t {
  396. monitor_t& lock;
  397. public:
  398. monitor_locker_t(monitor_t& newLock) : lock(newLock) { lock.enter(); }
  399. ~monitor_locker_t() { lock.leave(); }
  400. };
  401. class recursive_mutex_locker_t : nocopy_t {
  402. recursive_mutex_t& lock;
  403. public:
  404. recursive_mutex_locker_t(recursive_mutex_t& newLock)
  405. : lock(newLock) { lock.lock(); }
  406. ~recursive_mutex_locker_t() { lock.unlock(); }
  407. };
  408. /* Exceptions */
  409. struct alt_handler_list;
  410. extern void exception_init(void);
  411. extern void _destroyAltHandlerList(struct alt_handler_list *list);
  412. /* Class change notifications (gdb only for now) */
  413. #define OBJC_CLASS_ADDED (1<<0)
  414. #define OBJC_CLASS_REMOVED (1<<1)
  415. #define OBJC_CLASS_IVARS_CHANGED (1<<2)
  416. #define OBJC_CLASS_METHODS_CHANGED (1<<3)
  417. extern void gdb_objc_class_changed(Class cls, unsigned long changes, const char *classname)
  418. __attribute__((noinline));
  419. // Settings from environment variables
  420. #define OPTION(var, env, help) extern bool var;
  421. #include "objc-env.h"
  422. #undef OPTION
  423. extern void environ_init(void);
  424. extern void logReplacedMethod(const char *className, SEL s, bool isMeta, const char *catName, IMP oldImp, IMP newImp);
  425. // objc per-thread storage
  426. typedef struct {
  427. struct _objc_initializing_classes *initializingClasses; // for +initialize
  428. struct SyncCache *syncCache; // for @synchronize
  429. struct alt_handler_list *handlerList; // for exception alt handlers
  430. char *printableNames[4]; // temporary demangled names for logging
  431. // If you add new fields here, don't forget to update
  432. // _objc_pthread_destroyspecific()
  433. } _objc_pthread_data;
  434. extern _objc_pthread_data *_objc_fetch_pthread_data(bool create);
  435. extern void tls_init(void);
  436. // encoding.h
  437. extern unsigned int encoding_getNumberOfArguments(const char *typedesc);
  438. extern unsigned int encoding_getSizeOfArguments(const char *typedesc);
  439. extern unsigned int encoding_getArgumentInfo(const char *typedesc, unsigned int arg, const char **type, int *offset);
  440. extern void encoding_getReturnType(const char *t, char *dst, size_t dst_len);
  441. extern char * encoding_copyReturnType(const char *t);
  442. extern void encoding_getArgumentType(const char *t, unsigned int index, char *dst, size_t dst_len);
  443. extern char *encoding_copyArgumentType(const char *t, unsigned int index);
  444. // sync.h
  445. extern void _destroySyncCache(struct SyncCache *cache);
  446. // arr
  447. extern void arr_init(void);
  448. extern id objc_autoreleaseReturnValue(id obj);
  449. // block trampolines
  450. extern IMP _imp_implementationWithBlockNoCopy(id block);
  451. // layout.h
  452. typedef struct {
  453. uint8_t *bits;
  454. size_t bitCount;
  455. size_t bitsAllocated;
  456. bool weak;
  457. } layout_bitmap;
  458. extern layout_bitmap layout_bitmap_create(const unsigned char *layout_string, size_t layoutStringInstanceSize, size_t instanceSize, bool weak);
  459. extern layout_bitmap layout_bitmap_create_empty(size_t instanceSize, bool weak);
  460. extern void layout_bitmap_free(layout_bitmap bits);
  461. extern const unsigned char *layout_string_create(layout_bitmap bits);
  462. extern void layout_bitmap_set_ivar(layout_bitmap bits, const char *type, size_t offset);
  463. extern void layout_bitmap_grow(layout_bitmap *bits, size_t newCount);
  464. extern void layout_bitmap_slide(layout_bitmap *bits, size_t oldPos, size_t newPos);
  465. extern void layout_bitmap_slide_anywhere(layout_bitmap *bits, size_t oldPos, size_t newPos);
  466. extern bool layout_bitmap_splat(layout_bitmap dst, layout_bitmap src,
  467. size_t oldSrcInstanceSize);
  468. extern bool layout_bitmap_or(layout_bitmap dst, layout_bitmap src, const char *msg);
  469. extern bool layout_bitmap_clear(layout_bitmap dst, layout_bitmap src, const char *msg);
  470. extern void layout_bitmap_print(layout_bitmap bits);
  471. // fixme runtime
  472. extern bool MultithreadedForkChild;
  473. extern id objc_noop_imp(id self, SEL _cmd);
  474. extern Class look_up_class(const char *aClassName, bool includeUnconnected, bool includeClassHandler);
  475. extern "C" void map_images(unsigned count, const char * const paths[],
  476. const struct mach_header * const mhdrs[]);
  477. extern void map_images_nolock(unsigned count, const char * const paths[],
  478. const struct mach_header * const mhdrs[]);
  479. extern void load_images(const char *path, const struct mach_header *mh);
  480. extern void unmap_image(const char *path, const struct mach_header *mh);
  481. extern void unmap_image_nolock(const struct mach_header *mh);
  482. extern void _read_images(header_info **hList, uint32_t hCount, int totalClasses, int unoptimizedTotalClass);
  483. extern void _unload_image(header_info *hi);
  484. extern const header_info *_headerForClass(Class cls);
  485. extern Class _class_remap(Class cls);
  486. extern Class _class_getNonMetaClass(Class cls, id obj);
  487. extern Ivar _class_getVariable(Class cls, const char *name);
  488. extern unsigned _class_createInstancesFromZone(Class cls, size_t extraBytes, void *zone, id *results, unsigned num_requested);
  489. extern id _objc_constructOrFree(id bytes, Class cls);
  490. extern const char *_category_getName(Category cat);
  491. extern const char *_category_getClassName(Category cat);
  492. extern Class _category_getClass(Category cat);
  493. extern IMP _category_getLoadMethod(Category cat);
  494. extern id object_cxxConstructFromClass(id obj, Class cls);
  495. extern void object_cxxDestruct(id obj);
  496. extern void _class_resolveMethod(Class cls, SEL sel, id inst);
  497. extern void fixupCopiedIvars(id newObject, id oldObject);
  498. extern Class _class_getClassForIvar(Class cls, Ivar ivar);
  499. #define OBJC_WARN_DEPRECATED \
  500. do { \
  501. static int warned = 0; \
  502. if (!warned) { \
  503. warned = 1; \
  504. _objc_inform_deprecated(__FUNCTION__, NULL); \
  505. } \
  506. } while (0) \
  507. __END_DECLS
  508. #ifndef STATIC_ASSERT
  509. # define STATIC_ASSERT(x) _STATIC_ASSERT2(x, __LINE__)
  510. # define _STATIC_ASSERT2(x, line) _STATIC_ASSERT3(x, line)
  511. # define _STATIC_ASSERT3(x, line) \
  512. typedef struct { \
  513. int _static_assert[(x) ? 0 : -1]; \
  514. } _static_assert_ ## line __attribute__((unavailable))
  515. #endif
  516. #define countof(arr) (sizeof(arr) / sizeof((arr)[0]))
  517. static __inline uint32_t _objc_strhash(const char *s) {
  518. uint32_t hash = 0;
  519. for (;;) {
  520. int a = *s++;
  521. if (0 == a) break;
  522. hash += (hash << 8) + a;
  523. }
  524. return hash;
  525. }
  526. #if __cplusplus
  527. template <typename T>
  528. static inline T log2u(T x) {
  529. return (x<2) ? 0 : log2u(x>>1)+1;
  530. }
  531. template <typename T>
  532. static inline T exp2u(T x) {
  533. return (1 << x);
  534. }
  535. template <typename T>
  536. static T exp2m1u(T x) {
  537. return (1 << x) - 1;
  538. }
  539. #endif
  540. // Misalignment-safe integer types
  541. __attribute__((aligned(1))) typedef uintptr_t unaligned_uintptr_t;
  542. __attribute__((aligned(1))) typedef intptr_t unaligned_intptr_t;
  543. __attribute__((aligned(1))) typedef uint64_t unaligned_uint64_t;
  544. __attribute__((aligned(1))) typedef int64_t unaligned_int64_t;
  545. __attribute__((aligned(1))) typedef uint32_t unaligned_uint32_t;
  546. __attribute__((aligned(1))) typedef int32_t unaligned_int32_t;
  547. __attribute__((aligned(1))) typedef uint16_t unaligned_uint16_t;
  548. __attribute__((aligned(1))) typedef int16_t unaligned_int16_t;
  549. // Global operator new and delete. We must not use any app overrides.
  550. // This ALSO REQUIRES each of these be in libobjc's unexported symbol list.
  551. #if __cplusplus
  552. #pragma clang diagnostic push
  553. #pragma clang diagnostic ignored "-Winline-new-delete"
  554. #include <new>
  555. inline void* operator new(std::size_t size) throw (std::bad_alloc) { return malloc(size); }
  556. inline void* operator new[](std::size_t size) throw (std::bad_alloc) { return malloc(size); }
  557. inline void* operator new(std::size_t size, const std::nothrow_t&) throw() { return malloc(size); }
  558. inline void* operator new[](std::size_t size, const std::nothrow_t&) throw() { return malloc(size); }
  559. inline void operator delete(void* p) throw() { free(p); }
  560. inline void operator delete[](void* p) throw() { free(p); }
  561. inline void operator delete(void* p, const std::nothrow_t&) throw() { free(p); }
  562. inline void operator delete[](void* p, const std::nothrow_t&) throw() { free(p); }
  563. #pragma clang diagnostic pop
  564. #endif
  565. class TimeLogger {
  566. uint64_t mStart;
  567. bool mRecord;
  568. public:
  569. TimeLogger(bool record = true)
  570. : mStart(nanoseconds())
  571. , mRecord(record)
  572. { }
  573. void log(const char *msg) {
  574. if (mRecord) {
  575. uint64_t end = nanoseconds();
  576. _objc_inform("%.2f ms: %s", (end - mStart) / 1000000.0, msg);
  577. mStart = nanoseconds();
  578. }
  579. }
  580. };
  581. enum { CacheLineSize = 64 };
  582. // StripedMap<T> is a map of void* -> T, sized appropriately
  583. // for cache-friendly lock striping.
  584. // For example, this may be used as StripedMap<spinlock_t>
  585. // or as StripedMap<SomeStruct> where SomeStruct stores a spin lock.
  586. template<typename T>
  587. class StripedMap {
  588. #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
  589. enum { StripeCount = 8 };
  590. #else
  591. enum { StripeCount = 64 };
  592. #endif
  593. struct PaddedT {
  594. T value alignas(CacheLineSize);
  595. };
  596. PaddedT array[StripeCount];
  597. static unsigned int indexForPointer(const void *p) {
  598. uintptr_t addr = reinterpret_cast<uintptr_t>(p);
  599. return ((addr >> 4) ^ (addr >> 9)) % StripeCount;
  600. }
  601. public:
  602. T& operator[] (const void *p) {
  603. return array[indexForPointer(p)].value;
  604. }
  605. const T& operator[] (const void *p) const {
  606. return const_cast<StripedMap<T>>(this)[p];
  607. }
  608. // Shortcuts for StripedMaps of locks.
  609. void lockAll() {
  610. for (unsigned int i = 0; i < StripeCount; i++) {
  611. array[i].value.lock();
  612. }
  613. }
  614. void unlockAll() {
  615. for (unsigned int i = 0; i < StripeCount; i++) {
  616. array[i].value.unlock();
  617. }
  618. }
  619. void forceResetAll() {
  620. for (unsigned int i = 0; i < StripeCount; i++) {
  621. array[i].value.forceReset();
  622. }
  623. }
  624. void defineLockOrder() {
  625. for (unsigned int i = 1; i < StripeCount; i++) {
  626. lockdebug_lock_precedes_lock(&array[i-1].value, &array[i].value);
  627. }
  628. }
  629. void precedeLock(const void *newlock) {
  630. // assumes defineLockOrder is also called
  631. lockdebug_lock_precedes_lock(&array[StripeCount-1].value, newlock);
  632. }
  633. void succeedLock(const void *oldlock) {
  634. // assumes defineLockOrder is also called
  635. lockdebug_lock_precedes_lock(oldlock, &array[0].value);
  636. }
  637. const void *getLock(int i) {
  638. if (i < StripeCount) return &array[i].value;
  639. else return nil;
  640. }
  641. #if DEBUG
  642. StripedMap() {
  643. // Verify alignment expectations.
  644. uintptr_t base = (uintptr_t)&array[0].value;
  645. uintptr_t delta = (uintptr_t)&array[1].value - base;
  646. assert(delta % CacheLineSize == 0);
  647. assert(base % CacheLineSize == 0);
  648. }
  649. #else
  650. constexpr StripedMap() {}
  651. #endif
  652. };
  653. // DisguisedPtr<T> acts like pointer type T*, except the
  654. // stored value is disguised to hide it from tools like `leaks`.
  655. // nil is disguised as itself so zero-filled memory works as expected,
  656. // which means 0x80..00 is also disguised as itself but we don't care.
  657. // Note that weak_entry_t knows about this encoding.
  658. template <typename T>
  659. class DisguisedPtr {
  660. uintptr_t value;
  661. static uintptr_t disguise(T* ptr) {
  662. return -(uintptr_t)ptr;
  663. }
  664. static T* undisguise(uintptr_t val) {
  665. return (T*)-val;
  666. }
  667. public:
  668. DisguisedPtr() { }
  669. DisguisedPtr(T* ptr)
  670. : value(disguise(ptr)) { }
  671. DisguisedPtr(const DisguisedPtr<T>& ptr)
  672. : value(ptr.value) { }
  673. DisguisedPtr<T>& operator = (T* rhs) {
  674. value = disguise(rhs);
  675. return *this;
  676. }
  677. DisguisedPtr<T>& operator = (const DisguisedPtr<T>& rhs) {
  678. value = rhs.value;
  679. return *this;
  680. }
  681. operator T* () const {
  682. return undisguise(value);
  683. }
  684. T* operator -> () const {
  685. return undisguise(value);
  686. }
  687. T& operator * () const {
  688. return *undisguise(value);
  689. }
  690. T& operator [] (size_t i) const {
  691. return undisguise(value)[i];
  692. }
  693. // pointer arithmetic operators omitted
  694. // because we don't currently use them anywhere
  695. };
  696. // fixme type id is weird and not identical to objc_object*
  697. static inline bool operator == (DisguisedPtr<objc_object> lhs, id rhs) {
  698. return lhs == (objc_object *)rhs;
  699. }
  700. static inline bool operator != (DisguisedPtr<objc_object> lhs, id rhs) {
  701. return lhs != (objc_object *)rhs;
  702. }
  703. // Storage for a thread-safe chained hook function.
  704. // get() returns the value for calling.
  705. // set() installs a new function and returns the old one for chaining.
  706. // More precisely, set() writes the old value to a variable supplied by
  707. // the caller. get() and set() use appropriate barriers so that the
  708. // old value is safely written to the variable before the new value is
  709. // called to use it.
  710. //
  711. // T1: store to old variable; store-release to hook variable
  712. // T2: load-acquire from hook variable; call it; called hook loads old variable
  713. template <typename Fn>
  714. class ChainedHookFunction {
  715. std::atomic<Fn> hook{nil};
  716. public:
  717. ChainedHookFunction(Fn f) : hook{f} { };
  718. Fn get() {
  719. return hook.load(std::memory_order_acquire);
  720. }
  721. void set(Fn newValue, Fn *oldVariable)
  722. {
  723. Fn oldValue = hook.load(std::memory_order_relaxed);
  724. do {
  725. *oldVariable = oldValue;
  726. } while (!hook.compare_exchange_weak(oldValue, newValue,
  727. std::memory_order_release,
  728. std::memory_order_relaxed));
  729. }
  730. };
  731. // Pointer hash function.
  732. // This is not a terrific hash, but it is fast
  733. // and not outrageously flawed for our purposes.
  734. // Based on principles from http://locklessinc.com/articles/fast_hash/
  735. // and evaluation ideas from http://floodyberry.com/noncryptohashzoo/
  736. #if __LP64__
  737. static inline uint32_t ptr_hash(uint64_t key)
  738. {
  739. key ^= key >> 4;
  740. key *= 0x8a970be7488fda55;
  741. key ^= __builtin_bswap64(key);
  742. return (uint32_t)key;
  743. }
  744. #else
  745. static inline uint32_t ptr_hash(uint32_t key)
  746. {
  747. key ^= key >> 4;
  748. key *= 0x5052acdb;
  749. key ^= __builtin_bswap32(key);
  750. return key;
  751. }
  752. #endif
  753. /*
  754. Higher-quality hash function. This is measurably slower in some workloads.
  755. #if __LP64__
  756. uint32_t ptr_hash(uint64_t key)
  757. {
  758. key -= __builtin_bswap64(key);
  759. key *= 0x8a970be7488fda55;
  760. key ^= __builtin_bswap64(key);
  761. key *= 0x8a970be7488fda55;
  762. key ^= __builtin_bswap64(key);
  763. return (uint32_t)key;
  764. }
  765. #else
  766. static uint32_t ptr_hash(uint32_t key)
  767. {
  768. key -= __builtin_bswap32(key);
  769. key *= 0x5052acdb;
  770. key ^= __builtin_bswap32(key);
  771. key *= 0x5052acdb;
  772. key ^= __builtin_bswap32(key);
  773. return key;
  774. }
  775. #endif
  776. */
  777. // Lock declarations
  778. #include "objc-locks.h"
  779. // Inlined parts of objc_object's implementation
  780. #include "objc-object.h"
  781. #endif /* _OBJC_PRIVATE_H_ */