Block_private.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. /*
  2. * Block_private.h
  3. *
  4. * SPI for Blocks
  5. *
  6. * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
  7. *
  8. * @APPLE_LLVM_LICENSE_HEADER@
  9. *
  10. */
  11. #ifndef _BLOCK_PRIVATE_H_
  12. #define _BLOCK_PRIVATE_H_
  13. #include <Availability.h>
  14. #include <AvailabilityMacros.h>
  15. #include <TargetConditionals.h>
  16. #include <stdbool.h>
  17. #include <stdint.h>
  18. #include <stdio.h>
  19. #include <Block.h>
  20. #if __has_include(<ptrauth.h>)
  21. #include <ptrauth.h>
  22. #endif
  23. #if __has_feature(ptrauth_calls) && __cplusplus < 201103L
  24. // C ptrauth or old C++ ptrauth
  25. #define _Block_set_function_pointer(field, value) \
  26. ((value) \
  27. ? ((field) = \
  28. (__typeof__(field)) \
  29. ptrauth_auth_and_resign((void*)(value), \
  30. ptrauth_key_function_pointer, 0, \
  31. ptrauth_key_block_function, &(field))) \
  32. : ((field) = 0))
  33. #define _Block_get_function_pointer(field) \
  34. ((field) \
  35. ? (__typeof__(field)) \
  36. ptrauth_auth_function((void*)(field), \
  37. ptrauth_key_block_function, &(field)) \
  38. : (__typeof__(field))0)
  39. #else
  40. // C++11 ptrauth or no ptrauth
  41. #define _Block_set_function_pointer(field, value) \
  42. (field) = (value)
  43. #define _Block_get_function_pointer(field) \
  44. (field)
  45. #endif
  46. #if __has_feature(ptrauth_calls) && __cplusplus >= 201103L
  47. // StorageSignedFunctionPointer<Key, Fn> stores a function pointer of type
  48. // Fn but signed with the given ptrauth key and with the address of its
  49. // storage as extra data.
  50. // Function pointers inside block objects are signed this way.
  51. template <typename Fn, ptrauth_key Key>
  52. class StorageSignedFunctionPointer {
  53. uintptr_t bits;
  54. public:
  55. // Authenticate function pointer fn as a C function pointer.
  56. // Re-sign it with our key and the storage address as extra data.
  57. // DOES NOT actually write to our storage.
  58. uintptr_t prepareWrite(Fn fn) const
  59. {
  60. if (fn == nullptr) {
  61. return 0;
  62. } else {
  63. return (uintptr_t)
  64. ptrauth_auth_and_resign(fn, ptrauth_key_function_pointer, 0,
  65. Key, &bits);
  66. }
  67. }
  68. // Authenticate otherBits at otherStorage.
  69. // Re-sign it with our storage address.
  70. // DOES NOT actually write to our storage.
  71. uintptr_t prepareWrite(const StorageSignedFunctionPointer& other) const
  72. {
  73. if (other.bits == 0) {
  74. return 0;
  75. } else {
  76. return (uintptr_t)
  77. ptrauth_auth_and_resign((void*)other.bits, Key, &other.bits,
  78. Key, &bits);
  79. }
  80. }
  81. // Authenticate ptr as if it were stored at our storage address.
  82. // Re-sign it as a C function pointer.
  83. // DOES NOT actually read from our storage.
  84. Fn completeReadFn(uintptr_t ptr) const
  85. {
  86. if (ptr == 0) {
  87. return nullptr;
  88. } else {
  89. return ptrauth_auth_function((Fn)ptr, Key, &bits);
  90. }
  91. }
  92. // Authenticate ptr as if it were at our storage address.
  93. // Return it as a dereferenceable pointer.
  94. // DOES NOT actually read from our storage.
  95. void* completeReadRaw(uintptr_t ptr) const
  96. {
  97. if (ptr == 0) {
  98. return nullptr;
  99. } else {
  100. return ptrauth_auth_data((void*)ptr, Key, &bits);
  101. }
  102. }
  103. StorageSignedFunctionPointer() { }
  104. StorageSignedFunctionPointer(Fn value)
  105. : bits(prepareWrite(value)) { }
  106. StorageSignedFunctionPointer(const StorageSignedFunctionPointer& value)
  107. : bits(prepareWrite(value)) { }
  108. StorageSignedFunctionPointer&
  109. operator = (Fn rhs) {
  110. bits = prepareWrite(rhs);
  111. return *this;
  112. }
  113. StorageSignedFunctionPointer&
  114. operator = (const StorageSignedFunctionPointer& rhs) {
  115. bits = prepareWrite(rhs);
  116. return *this;
  117. }
  118. operator Fn () const {
  119. return completeReadFn(bits);
  120. }
  121. explicit operator void* () const {
  122. return completeReadRaw(bits);
  123. }
  124. explicit operator bool () const {
  125. return completeReadRaw(bits) != nullptr;
  126. }
  127. };
  128. using BlockCopyFunction = StorageSignedFunctionPointer
  129. <void(*)(void *, const void *),
  130. ptrauth_key_block_function>;
  131. using BlockDisposeFunction = StorageSignedFunctionPointer
  132. <void(*)(const void *),
  133. ptrauth_key_block_function>;
  134. using BlockInvokeFunction = StorageSignedFunctionPointer
  135. <void(*)(void *, ...),
  136. ptrauth_key_block_function>;
  137. using BlockByrefKeepFunction = StorageSignedFunctionPointer
  138. <void(*)(struct Block_byref *, struct Block_byref *),
  139. ptrauth_key_block_function>;
  140. using BlockByrefDestroyFunction = StorageSignedFunctionPointer
  141. <void(*)(struct Block_byref *),
  142. ptrauth_key_block_function>;
  143. // c++11 and ptrauth_calls
  144. #elif !__has_feature(ptrauth_calls)
  145. // not ptrauth_calls
  146. typedef void(*BlockCopyFunction)(void *, const void *);
  147. typedef void(*BlockDisposeFunction)(const void *);
  148. typedef void(*BlockInvokeFunction)(void *, ...);
  149. typedef void(*BlockByrefKeepFunction)(struct Block_byref*, struct Block_byref*);
  150. typedef void(*BlockByrefDestroyFunction)(struct Block_byref *);
  151. #else
  152. // ptrauth_calls but not c++11
  153. typedef uintptr_t BlockCopyFunction;
  154. typedef uintptr_t BlockDisposeFunction;
  155. typedef uintptr_t BlockInvokeFunction;
  156. typedef uintptr_t BlockByrefKeepFunction;
  157. typedef uintptr_t BlockByrefDestroyFunction;
  158. #endif
  159. // Values for Block_layout->flags to describe block objects
  160. enum {
  161. BLOCK_DEALLOCATING = (0x0001), // runtime
  162. BLOCK_REFCOUNT_MASK = (0xfffe), // runtime
  163. BLOCK_NEEDS_FREE = (1 << 24), // runtime
  164. BLOCK_HAS_COPY_DISPOSE = (1 << 25), // compiler
  165. BLOCK_HAS_CTOR = (1 << 26), // compiler: helpers have C++ code
  166. BLOCK_IS_GC = (1 << 27), // runtime
  167. BLOCK_IS_GLOBAL = (1 << 28), // compiler
  168. BLOCK_USE_STRET = (1 << 29), // compiler: undefined if !BLOCK_HAS_SIGNATURE
  169. BLOCK_HAS_SIGNATURE = (1 << 30), // compiler
  170. BLOCK_HAS_EXTENDED_LAYOUT=(1 << 31) // compiler
  171. };
  172. #define BLOCK_DESCRIPTOR_1 1
  173. struct Block_descriptor_1 {
  174. uintptr_t reserved;
  175. uintptr_t size;
  176. };
  177. #define BLOCK_DESCRIPTOR_2 1
  178. struct Block_descriptor_2 {
  179. // requires BLOCK_HAS_COPY_DISPOSE
  180. BlockCopyFunction copy;
  181. BlockDisposeFunction dispose;
  182. };
  183. #define BLOCK_DESCRIPTOR_3 1
  184. struct Block_descriptor_3 {
  185. // requires BLOCK_HAS_SIGNATURE
  186. const char *signature;
  187. const char *layout; // contents depend on BLOCK_HAS_EXTENDED_LAYOUT
  188. };
  189. struct Block_layout {
  190. void *isa;
  191. volatile int32_t flags; // contains ref count
  192. int32_t reserved;
  193. BlockInvokeFunction invoke;
  194. struct Block_descriptor_1 *descriptor;
  195. // imported variables
  196. };
  197. // Values for Block_byref->flags to describe __block variables
  198. enum {
  199. // Byref refcount must use the same bits as Block_layout's refcount.
  200. // BLOCK_DEALLOCATING = (0x0001), // runtime
  201. // BLOCK_REFCOUNT_MASK = (0xfffe), // runtime
  202. BLOCK_BYREF_LAYOUT_MASK = (0xf << 28), // compiler
  203. BLOCK_BYREF_LAYOUT_EXTENDED = ( 1 << 28), // compiler
  204. BLOCK_BYREF_LAYOUT_NON_OBJECT = ( 2 << 28), // compiler
  205. BLOCK_BYREF_LAYOUT_STRONG = ( 3 << 28), // compiler
  206. BLOCK_BYREF_LAYOUT_WEAK = ( 4 << 28), // compiler
  207. BLOCK_BYREF_LAYOUT_UNRETAINED = ( 5 << 28), // compiler
  208. BLOCK_BYREF_IS_GC = ( 1 << 27), // runtime
  209. BLOCK_BYREF_HAS_COPY_DISPOSE = ( 1 << 25), // compiler
  210. BLOCK_BYREF_NEEDS_FREE = ( 1 << 24), // runtime
  211. };
  212. struct Block_byref {
  213. void *isa;
  214. struct Block_byref *forwarding;
  215. volatile int32_t flags; // contains ref count
  216. uint32_t size;
  217. };
  218. struct Block_byref_2 {
  219. // requires BLOCK_BYREF_HAS_COPY_DISPOSE
  220. BlockByrefKeepFunction byref_keep;
  221. BlockByrefDestroyFunction byref_destroy;
  222. };
  223. struct Block_byref_3 {
  224. // requires BLOCK_BYREF_LAYOUT_EXTENDED
  225. const char *layout;
  226. };
  227. // Extended layout encoding.
  228. // Values for Block_descriptor_3->layout with BLOCK_HAS_EXTENDED_LAYOUT
  229. // and for Block_byref_3->layout with BLOCK_BYREF_LAYOUT_EXTENDED
  230. // If the layout field is less than 0x1000, then it is a compact encoding
  231. // of the form 0xXYZ: X strong pointers, then Y byref pointers,
  232. // then Z weak pointers.
  233. // If the layout field is 0x1000 or greater, it points to a
  234. // string of layout bytes. Each byte is of the form 0xPN.
  235. // Operator P is from the list below. Value N is a parameter for the operator.
  236. // Byte 0x00 terminates the layout; remaining block data is non-pointer bytes.
  237. enum {
  238. BLOCK_LAYOUT_ESCAPE = 0, // N=0 halt, rest is non-pointer. N!=0 reserved.
  239. BLOCK_LAYOUT_NON_OBJECT_BYTES = 1, // N bytes non-objects
  240. BLOCK_LAYOUT_NON_OBJECT_WORDS = 2, // N words non-objects
  241. BLOCK_LAYOUT_STRONG = 3, // N words strong pointers
  242. BLOCK_LAYOUT_BYREF = 4, // N words byref pointers
  243. BLOCK_LAYOUT_WEAK = 5, // N words weak pointers
  244. BLOCK_LAYOUT_UNRETAINED = 6, // N words unretained pointers
  245. BLOCK_LAYOUT_UNKNOWN_WORDS_7 = 7, // N words, reserved
  246. BLOCK_LAYOUT_UNKNOWN_WORDS_8 = 8, // N words, reserved
  247. BLOCK_LAYOUT_UNKNOWN_WORDS_9 = 9, // N words, reserved
  248. BLOCK_LAYOUT_UNKNOWN_WORDS_A = 0xA, // N words, reserved
  249. BLOCK_LAYOUT_UNUSED_B = 0xB, // unspecified, reserved
  250. BLOCK_LAYOUT_UNUSED_C = 0xC, // unspecified, reserved
  251. BLOCK_LAYOUT_UNUSED_D = 0xD, // unspecified, reserved
  252. BLOCK_LAYOUT_UNUSED_E = 0xE, // unspecified, reserved
  253. BLOCK_LAYOUT_UNUSED_F = 0xF, // unspecified, reserved
  254. };
  255. // Runtime support functions used by compiler when generating copy/dispose helpers
  256. // Values for _Block_object_assign() and _Block_object_dispose() parameters
  257. enum {
  258. // see function implementation for a more complete description of these fields and combinations
  259. BLOCK_FIELD_IS_OBJECT = 3, // id, NSObject, __attribute__((NSObject)), block, ...
  260. BLOCK_FIELD_IS_BLOCK = 7, // a block variable
  261. BLOCK_FIELD_IS_BYREF = 8, // the on stack structure holding the __block variable
  262. BLOCK_FIELD_IS_WEAK = 16, // declared __weak, only used in byref copy helpers
  263. BLOCK_BYREF_CALLER = 128, // called from __block (byref) copy/dispose support routines.
  264. };
  265. enum {
  266. BLOCK_ALL_COPY_DISPOSE_FLAGS =
  267. BLOCK_FIELD_IS_OBJECT | BLOCK_FIELD_IS_BLOCK | BLOCK_FIELD_IS_BYREF |
  268. BLOCK_FIELD_IS_WEAK | BLOCK_BYREF_CALLER
  269. };
  270. // Function pointer accessors
  271. static inline __typeof__(void (*)(void *, ...))
  272. _Block_get_invoke_fn(struct Block_layout *block)
  273. {
  274. return (void (*)(void *, ...))_Block_get_function_pointer(block->invoke);
  275. }
  276. static inline void
  277. _Block_set_invoke_fn(struct Block_layout *block, void (*fn)(void *, ...))
  278. {
  279. _Block_set_function_pointer(block->invoke, fn);
  280. }
  281. static inline __typeof__(void (*)(void *, const void *))
  282. _Block_get_copy_fn(struct Block_descriptor_2 *desc)
  283. {
  284. return (void (*)(void *, const void *))_Block_get_function_pointer(desc->copy);
  285. }
  286. static inline void
  287. _Block_set_copy_fn(struct Block_descriptor_2 *desc,
  288. void (*fn)(void *, const void *))
  289. {
  290. _Block_set_function_pointer(desc->copy, fn);
  291. }
  292. static inline __typeof__(void (*)(const void *))
  293. _Block_get_dispose_fn(struct Block_descriptor_2 *desc)
  294. {
  295. return (void (*)(const void *))_Block_get_function_pointer(desc->dispose);
  296. }
  297. static inline void
  298. _Block_set_dispose_fn(struct Block_descriptor_2 *desc,
  299. void (*fn)(const void *))
  300. {
  301. _Block_set_function_pointer(desc->dispose, fn);
  302. }
  303. // Other support functions
  304. // runtime entry to get total size of a closure
  305. BLOCK_EXPORT size_t Block_size(void *aBlock);
  306. // indicates whether block was compiled with compiler that sets the ABI related metadata bits
  307. BLOCK_EXPORT bool _Block_has_signature(void *aBlock)
  308. __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
  309. // returns TRUE if return value of block is on the stack, FALSE otherwise
  310. BLOCK_EXPORT bool _Block_use_stret(void *aBlock)
  311. __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
  312. // Returns a string describing the block's parameter and return types.
  313. // The encoding scheme is the same as Objective-C @encode.
  314. // Returns NULL for blocks compiled with some compilers.
  315. BLOCK_EXPORT const char * _Block_signature(void *aBlock)
  316. __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
  317. // Returns a string describing the block's GC layout.
  318. // This uses the GC skip/scan encoding.
  319. // May return NULL.
  320. BLOCK_EXPORT const char * _Block_layout(void *aBlock)
  321. __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
  322. // Returns a string describing the block's layout.
  323. // This uses the "extended layout" form described above.
  324. // May return NULL.
  325. BLOCK_EXPORT const char * _Block_extended_layout(void *aBlock)
  326. __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_7_0);
  327. // Callable only from the ARR weak subsystem while in exclusion zone
  328. BLOCK_EXPORT bool _Block_tryRetain(const void *aBlock)
  329. __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
  330. // Callable only from the ARR weak subsystem while in exclusion zone
  331. BLOCK_EXPORT bool _Block_isDeallocating(const void *aBlock)
  332. __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
  333. // the raw data space for runtime classes for blocks
  334. // class+meta used for stack, malloc, and collectable based blocks
  335. BLOCK_EXPORT void * _NSConcreteMallocBlock[32]
  336. __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
  337. BLOCK_EXPORT void * _NSConcreteAutoBlock[32]
  338. __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
  339. BLOCK_EXPORT void * _NSConcreteFinalizingBlock[32]
  340. __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
  341. BLOCK_EXPORT void * _NSConcreteWeakBlockVariable[32]
  342. __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);
  343. // declared in Block.h
  344. // BLOCK_EXPORT void * _NSConcreteGlobalBlock[32];
  345. // BLOCK_EXPORT void * _NSConcreteStackBlock[32];
  346. struct Block_callbacks_RR {
  347. size_t size; // size == sizeof(struct Block_callbacks_RR)
  348. void (*retain)(const void *);
  349. void (*release)(const void *);
  350. void (*destructInstance)(const void *);
  351. };
  352. typedef struct Block_callbacks_RR Block_callbacks_RR;
  353. BLOCK_EXPORT void _Block_use_RR2(const Block_callbacks_RR *callbacks);
  354. #endif