objc-runtime-old.mm 110 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343
  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-runtime-old.m
  25. * Support for old-ABI classes and images.
  26. **********************************************************************/
  27. /***********************************************************************
  28. * Class loading and connecting (GrP 2004-2-11)
  29. *
  30. * When images are loaded (during program startup or otherwise), the
  31. * runtime needs to load classes and categories from the images, connect
  32. * classes to superclasses and categories to parent classes, and call
  33. * +load methods.
  34. *
  35. * The Objective-C runtime can cope with classes arriving in any order.
  36. * That is, a class may be discovered by the runtime before some
  37. * superclass is known. To handle out-of-order class loads, the
  38. * runtime uses a "pending class" system.
  39. *
  40. * (Historical note)
  41. * Panther and earlier: many classes arrived out-of-order because of
  42. * the poorly-ordered callback from dyld. However, the runtime's
  43. * pending mechanism only handled "missing superclass" and not
  44. * "present superclass but missing higher class". See Radar #3225652.
  45. * Tiger: The runtime's pending mechanism was augmented to handle
  46. * arbitrary missing classes. In addition, dyld was rewritten and
  47. * now sends the callbacks in strictly bottom-up link order.
  48. * The pending mechanism may now be needed only for rare and
  49. * hard to construct programs.
  50. * (End historical note)
  51. *
  52. * A class when first seen in an image is considered "unconnected".
  53. * It is stored in `unconnected_class_hash`. If all of the class's
  54. * superclasses exist and are already "connected", then the new class
  55. * can be connected to its superclasses and moved to `class_hash` for
  56. * normal use. Otherwise, the class waits in `unconnected_class_hash`
  57. * until the superclasses finish connecting.
  58. *
  59. * A "connected" class is
  60. * (1) in `class_hash`,
  61. * (2) connected to its superclasses,
  62. * (3) has no unconnected superclasses,
  63. * (4) is otherwise initialized and ready for use, and
  64. * (5) is eligible for +load if +load has not already been called.
  65. *
  66. * An "unconnected" class is
  67. * (1) in `unconnected_class_hash`,
  68. * (2) not connected to its superclasses,
  69. * (3) has an immediate superclass which is either missing or unconnected,
  70. * (4) is not ready for use, and
  71. * (5) is not yet eligible for +load.
  72. *
  73. * Image mapping is NOT CURRENTLY THREAD-SAFE with respect to just about
  74. * anything. Image mapping IS RE-ENTRANT in several places: superclass
  75. * lookup may cause ZeroLink to load another image, and +load calls may
  76. * cause dyld to load another image.
  77. *
  78. * Image mapping sequence:
  79. *
  80. * Read all classes in all new images.
  81. * Add them all to unconnected_class_hash.
  82. * Note any +load implementations before categories are attached.
  83. * Attach any pending categories.
  84. * Read all categories in all new images.
  85. * Attach categories whose parent class exists (connected or not),
  86. * and pend the rest.
  87. * Mark them all eligible for +load (if implemented), even if the
  88. * parent class is missing.
  89. * Try to connect all classes in all new images.
  90. * If the superclass is missing, pend the class
  91. * If the superclass is unconnected, try to recursively connect it
  92. * If the superclass is connected:
  93. * connect the class
  94. * mark the class eligible for +load, if implemented
  95. * fix up any pended classrefs referring to the class
  96. * connect any pended subclasses of the class
  97. * Resolve selector refs and class refs in all new images.
  98. * Class refs whose classes still do not exist are pended.
  99. * Fix up protocol objects in all new images.
  100. * Call +load for classes and categories.
  101. * May include classes or categories that are not in these images,
  102. * but are newly eligible because of these image.
  103. * Class +loads will be called superclass-first because of the
  104. * superclass-first nature of the connecting process.
  105. * Category +load needs to be deferred until the parent class is
  106. * connected and has had its +load called.
  107. *
  108. * Performance: all classes are read before any categories are read.
  109. * Fewer categories need be pended for lack of a parent class.
  110. *
  111. * Performance: all categories are attempted to be attached before
  112. * any classes are connected. Fewer class caches need be flushed.
  113. * (Unconnected classes and their respective subclasses are guaranteed
  114. * to be un-messageable, so their caches will be empty.)
  115. *
  116. * Performance: all classes are read before any classes are connected.
  117. * Fewer classes need be pended for lack of a superclass.
  118. *
  119. * Correctness: all selector and class refs are fixed before any
  120. * protocol fixups or +load methods. libobjc itself contains selector
  121. * and class refs which are used in protocol fixup and +load.
  122. *
  123. * Correctness: +load methods are scheduled in bottom-up link order.
  124. * This constraint is in addition to superclass order. Some +load
  125. * implementations expect to use another class in a linked-to library,
  126. * even if the two classes don't share a direct superclass relationship.
  127. *
  128. * Correctness: all classes are scanned for +load before any categories
  129. * are attached. Otherwise, if a category implements +load and its class
  130. * has no class methods, the class's +load scan would find the category's
  131. * +load method, which would then be called twice.
  132. *
  133. * Correctness: pended class refs are not fixed up until the class is
  134. * connected. Classes with missing weak superclasses remain unconnected.
  135. * Class refs to classes with missing weak superclasses must be nil.
  136. * Therefore class refs to unconnected classes must remain un-fixed.
  137. *
  138. **********************************************************************/
  139. #if !__OBJC2__
  140. #include "objc-private.h"
  141. #include "objc-runtime-old.h"
  142. #include "objc-file-old.h"
  143. #include "objc-cache-old.h"
  144. #include "objc-loadmethod.h"
  145. typedef struct _objc_unresolved_category
  146. {
  147. struct _objc_unresolved_category *next;
  148. old_category *cat; // may be nil
  149. long version;
  150. } _objc_unresolved_category;
  151. typedef struct _PendingSubclass
  152. {
  153. Class subclass; // subclass to finish connecting; may be nil
  154. struct _PendingSubclass *next;
  155. } PendingSubclass;
  156. typedef struct _PendingClassRef
  157. {
  158. Class *ref; // class reference to fix up; may be nil
  159. // (ref & 1) is a metaclass reference
  160. struct _PendingClassRef *next;
  161. } PendingClassRef;
  162. static uintptr_t classHash(void *info, Class data);
  163. static int classIsEqual(void *info, Class name, Class cls);
  164. static int _objc_defaultClassHandler(const char *clsName);
  165. static inline NXMapTable *pendingClassRefsMapTable(void);
  166. static inline NXMapTable *pendingSubclassesMapTable(void);
  167. static void pendClassInstallation(Class cls, const char *superName);
  168. static void pendClassReference(Class *ref, const char *className, bool isMeta);
  169. static void resolve_references_to_class(Class cls);
  170. static void resolve_subclasses_of_class(Class cls);
  171. static void really_connect_class(Class cls, Class supercls);
  172. static bool connect_class(Class cls);
  173. static void map_method_descs (struct objc_method_description_list * methods, bool copy);
  174. static void _objcTweakMethodListPointerForClass(Class cls);
  175. static inline void _objc_add_category(Class cls, old_category *category, int version);
  176. static bool _objc_add_category_flush_caches(Class cls, old_category *category, int version);
  177. static _objc_unresolved_category *reverse_cat(_objc_unresolved_category *cat);
  178. static void resolve_categories_for_class(Class cls);
  179. static bool _objc_register_category(old_category *cat, int version);
  180. // Function called when a class is loaded from an image
  181. void (*callbackFunction)(Class, Category) = 0;
  182. // Hash table of classes
  183. NXHashTable * class_hash = 0;
  184. static NXHashTablePrototype classHashPrototype =
  185. {
  186. (uintptr_t (*) (const void *, const void *)) classHash,
  187. (int (*)(const void *, const void *, const void *)) classIsEqual,
  188. NXNoEffectFree, 0
  189. };
  190. // Hash table of unconnected classes
  191. static NXHashTable *unconnected_class_hash = nil;
  192. // Exported copy of class_hash variable (hook for debugging tools)
  193. NXHashTable *_objc_debug_class_hash = nil;
  194. // Category and class registries
  195. // Keys are COPIES of strings, to prevent stale pointers with unloaded bundles
  196. // Use NXMapKeyCopyingInsert and NXMapKeyFreeingRemove
  197. static NXMapTable * category_hash = nil;
  198. // Keys are COPIES of strings, to prevent stale pointers with unloaded bundles
  199. // Use NXMapKeyCopyingInsert and NXMapKeyFreeingRemove
  200. static NXMapTable * pendingClassRefsMap = nil;
  201. static NXMapTable * pendingSubclassesMap = nil;
  202. // Protocols
  203. static NXMapTable *protocol_map = nil; // name -> protocol
  204. static NXMapTable *protocol_ext_map = nil; // protocol -> protocol ext
  205. // Function pointer objc_getClass calls through when class is not found
  206. static int (*objc_classHandler) (const char *) = _objc_defaultClassHandler;
  207. // Function pointer called by objc_getClass and objc_lookupClass when
  208. // class is not found. _objc_classLoader is called before objc_classHandler.
  209. static BOOL (*_objc_classLoader)(const char *) = nil;
  210. /***********************************************************************
  211. * objc_dump_class_hash. Log names of all known classes.
  212. **********************************************************************/
  213. void objc_dump_class_hash(void)
  214. {
  215. NXHashTable *table;
  216. unsigned count;
  217. Class data;
  218. NXHashState state;
  219. table = class_hash;
  220. count = 0;
  221. state = NXInitHashState (table);
  222. while (NXNextHashState (table, &state, (void **) &data))
  223. printf ("class %d: %s\n", ++count, data->nameForLogging());
  224. }
  225. /***********************************************************************
  226. * _objc_init_class_hash. Return the class lookup table, create it if
  227. * necessary.
  228. **********************************************************************/
  229. void _objc_init_class_hash(void)
  230. {
  231. // Do nothing if class hash table already exists
  232. if (class_hash)
  233. return;
  234. // class_hash starts small, with only enough capacity for libobjc itself.
  235. // If a second library is found by map_images(), class_hash is immediately
  236. // resized to capacity 1024 to cut down on rehashes.
  237. // Old numbers: A smallish Foundation+AppKit program will have
  238. // about 520 classes. Larger apps (like IB or WOB) have more like
  239. // 800 classes. Some customers have massive quantities of classes.
  240. // Foundation-only programs aren't likely to notice the ~6K loss.
  241. class_hash = NXCreateHashTable(classHashPrototype, 16, nil);
  242. _objc_debug_class_hash = class_hash;
  243. }
  244. /***********************************************************************
  245. * objc_getClassList. Return the known classes.
  246. **********************************************************************/
  247. int objc_getClassList(Class *buffer, int bufferLen)
  248. {
  249. NXHashState state;
  250. Class cls;
  251. int cnt, num;
  252. mutex_locker_t lock(classLock);
  253. if (!class_hash) return 0;
  254. num = NXCountHashTable(class_hash);
  255. if (nil == buffer) return num;
  256. cnt = 0;
  257. state = NXInitHashState(class_hash);
  258. while (cnt < bufferLen &&
  259. NXNextHashState(class_hash, &state, (void **)&cls))
  260. {
  261. buffer[cnt++] = cls;
  262. }
  263. return num;
  264. }
  265. /***********************************************************************
  266. * objc_copyClassList
  267. * Returns pointers to all classes.
  268. * This requires all classes be realized, which is regretfully non-lazy.
  269. *
  270. * outCount may be nil. *outCount is the number of classes returned.
  271. * If the returned array is not nil, it is nil-terminated and must be
  272. * freed with free().
  273. * Locking: acquires classLock
  274. **********************************************************************/
  275. Class *
  276. objc_copyClassList(unsigned int *outCount)
  277. {
  278. Class *result;
  279. unsigned int count;
  280. mutex_locker_t lock(classLock);
  281. result = nil;
  282. count = class_hash ? NXCountHashTable(class_hash) : 0;
  283. if (count > 0) {
  284. Class cls;
  285. NXHashState state = NXInitHashState(class_hash);
  286. result = (Class *)malloc((1+count) * sizeof(Class));
  287. count = 0;
  288. while (NXNextHashState(class_hash, &state, (void **)&cls)) {
  289. result[count++] = cls;
  290. }
  291. result[count] = nil;
  292. }
  293. if (outCount) *outCount = count;
  294. return result;
  295. }
  296. /***********************************************************************
  297. * objc_copyProtocolList
  298. * Returns pointers to all protocols.
  299. * Locking: acquires classLock
  300. **********************************************************************/
  301. Protocol * __unsafe_unretained *
  302. objc_copyProtocolList(unsigned int *outCount)
  303. {
  304. int count, i;
  305. Protocol *proto;
  306. const char *name;
  307. NXMapState state;
  308. Protocol **result;
  309. mutex_locker_t lock(classLock);
  310. count = NXCountMapTable(protocol_map);
  311. if (count == 0) {
  312. if (outCount) *outCount = 0;
  313. return nil;
  314. }
  315. result = (Protocol **)calloc(1 + count, sizeof(Protocol *));
  316. i = 0;
  317. state = NXInitMapState(protocol_map);
  318. while (NXNextMapState(protocol_map, &state,
  319. (const void **)&name, (const void **)&proto))
  320. {
  321. result[i++] = proto;
  322. }
  323. result[i++] = nil;
  324. ASSERT(i == count+1);
  325. if (outCount) *outCount = count;
  326. return result;
  327. }
  328. /***********************************************************************
  329. * objc_getClasses. Return class lookup table.
  330. *
  331. * NOTE: This function is very dangerous, since you cannot safely use
  332. * the hashtable without locking it, and the lock is private!
  333. **********************************************************************/
  334. void *objc_getClasses(void)
  335. {
  336. OBJC_WARN_DEPRECATED;
  337. // Return the class lookup hash table
  338. return class_hash;
  339. }
  340. /***********************************************************************
  341. * classHash.
  342. **********************************************************************/
  343. static uintptr_t classHash(void *info, Class data)
  344. {
  345. // Nil classes hash to zero
  346. if (!data)
  347. return 0;
  348. // Call through to real hash function
  349. return _objc_strhash (data->mangledName());
  350. }
  351. /***********************************************************************
  352. * classIsEqual. Returns whether the class names match. If we ever
  353. * check more than the name, routines like objc_lookUpClass have to
  354. * change as well.
  355. **********************************************************************/
  356. static int classIsEqual(void *info, Class name, Class cls)
  357. {
  358. // Standard string comparison
  359. return strcmp(name->mangledName(), cls->mangledName()) == 0;
  360. }
  361. // Unresolved future classes
  362. static NXHashTable *future_class_hash = nil;
  363. // Resolved future<->original classes
  364. static NXMapTable *future_class_to_original_class_map = nil;
  365. static NXMapTable *original_class_to_future_class_map = nil;
  366. // CF requests about 20 future classes; HIToolbox requests one.
  367. #define FUTURE_COUNT 32
  368. /***********************************************************************
  369. * setOriginalClassForFutureClass
  370. * Record resolution of a future class.
  371. **********************************************************************/
  372. static void setOriginalClassForFutureClass(Class futureClass,
  373. Class originalClass)
  374. {
  375. if (!future_class_to_original_class_map) {
  376. future_class_to_original_class_map =
  377. NXCreateMapTable(NXPtrValueMapPrototype, FUTURE_COUNT);
  378. original_class_to_future_class_map =
  379. NXCreateMapTable(NXPtrValueMapPrototype, FUTURE_COUNT);
  380. }
  381. NXMapInsert (future_class_to_original_class_map,
  382. futureClass, originalClass);
  383. NXMapInsert (original_class_to_future_class_map,
  384. originalClass, futureClass);
  385. if (PrintFuture) {
  386. _objc_inform("FUTURE: using %p instead of %p for %s", (void*)futureClass, (void*)originalClass, originalClass->name);
  387. }
  388. }
  389. /***********************************************************************
  390. * getOriginalClassForFutureClass
  391. * getFutureClassForOriginalClass
  392. * Switch between a future class and its corresponding original class.
  393. * The future class is the one actually in use.
  394. * The original class is the one from disk.
  395. **********************************************************************/
  396. /*
  397. static Class
  398. getOriginalClassForFutureClass(Class futureClass)
  399. {
  400. if (!future_class_to_original_class_map) return Nil;
  401. return NXMapGet (future_class_to_original_class_map, futureClass);
  402. }
  403. */
  404. static Class
  405. getFutureClassForOriginalClass(Class originalClass)
  406. {
  407. if (!original_class_to_future_class_map) return Nil;
  408. return (Class)NXMapGet(original_class_to_future_class_map, originalClass);
  409. }
  410. /***********************************************************************
  411. * makeFutureClass
  412. * Initialize the memory in *cls with an unresolved future class with the
  413. * given name. The memory is recorded in future_class_hash.
  414. **********************************************************************/
  415. static void makeFutureClass(Class cls, const char *name)
  416. {
  417. // CF requests about 20 future classes, plus HIToolbox has one.
  418. if (!future_class_hash) {
  419. future_class_hash =
  420. NXCreateHashTable(classHashPrototype, FUTURE_COUNT, nil);
  421. }
  422. cls->name = strdup(name);
  423. NXHashInsert(future_class_hash, cls);
  424. if (PrintFuture) {
  425. _objc_inform("FUTURE: reserving %p for %s", (void*)cls, name);
  426. }
  427. }
  428. /***********************************************************************
  429. * _objc_allocateFutureClass
  430. * Allocate an unresolved future class for the given class name.
  431. * Returns any existing allocation if one was already made.
  432. * Assumes the named class doesn't exist yet.
  433. * Not thread safe.
  434. **********************************************************************/
  435. Class _objc_allocateFutureClass(const char *name)
  436. {
  437. Class cls;
  438. if (future_class_hash) {
  439. objc_class query;
  440. query.name = name;
  441. if ((cls = (Class)NXHashGet(future_class_hash, &query))) {
  442. // Already have a future class for this name.
  443. return cls;
  444. }
  445. }
  446. cls = _calloc_class(sizeof(objc_class));
  447. makeFutureClass(cls, name);
  448. return cls;
  449. }
  450. /***********************************************************************
  451. * objc_getFutureClass. Return the id of the named class.
  452. * If the class does not exist, return an uninitialized class
  453. * structure that will be used for the class when and if it
  454. * does get loaded.
  455. * Not thread safe.
  456. **********************************************************************/
  457. Class objc_getFutureClass(const char *name)
  458. {
  459. Class cls;
  460. // YES unconnected, NO class handler
  461. // (unconnected is OK because it will someday be the real class)
  462. cls = look_up_class(name, YES, NO);
  463. if (cls) {
  464. if (PrintFuture) {
  465. _objc_inform("FUTURE: found %p already in use for %s",
  466. (void*)cls, name);
  467. }
  468. return cls;
  469. }
  470. // No class or future class with that name yet. Make one.
  471. // fixme not thread-safe with respect to
  472. // simultaneous library load or getFutureClass.
  473. return _objc_allocateFutureClass(name);
  474. }
  475. BOOL _class_isFutureClass(Class cls)
  476. {
  477. return cls && cls->isFuture();
  478. }
  479. bool objc_class::isFuture()
  480. {
  481. return future_class_hash && NXHashGet(future_class_hash, this);
  482. }
  483. /***********************************************************************
  484. * _objc_defaultClassHandler. Default objc_classHandler. Does nothing.
  485. **********************************************************************/
  486. static int _objc_defaultClassHandler(const char *clsName)
  487. {
  488. // Return zero so objc_getClass doesn't bother re-searching
  489. return 0;
  490. }
  491. /***********************************************************************
  492. * objc_setClassHandler. Set objc_classHandler to the specified value.
  493. *
  494. * NOTE: This should probably deal with userSuppliedHandler being nil,
  495. * because the objc_classHandler caller does not check... it would bus
  496. * error. It would make sense to handle nil by restoring the default
  497. * handler. Is anyone hacking with this, though?
  498. **********************************************************************/
  499. void objc_setClassHandler(int (*userSuppliedHandler)(const char *))
  500. {
  501. OBJC_WARN_DEPRECATED;
  502. objc_classHandler = userSuppliedHandler;
  503. }
  504. /***********************************************************************
  505. * _objc_setClassLoader
  506. * Similar to objc_setClassHandler, but objc_classLoader is used for
  507. * both objc_getClass() and objc_lookupClass(), and objc_classLoader
  508. * pre-empts objc_classHandler.
  509. **********************************************************************/
  510. void _objc_setClassLoader(BOOL (*newClassLoader)(const char *))
  511. {
  512. _objc_classLoader = newClassLoader;
  513. }
  514. /***********************************************************************
  515. * objc_getProtocol
  516. * Get a protocol by name, or nil.
  517. **********************************************************************/
  518. Protocol *objc_getProtocol(const char *name)
  519. {
  520. mutex_locker_t lock(classLock);
  521. if (!protocol_map) return nil;
  522. return (Protocol *)NXMapGet(protocol_map, name);
  523. }
  524. /***********************************************************************
  525. * look_up_class
  526. * Map a class name to a class using various methods.
  527. * This is the common implementation of objc_lookUpClass and objc_getClass,
  528. * and is also used internally to get additional search options.
  529. * Sequence:
  530. * 1. class_hash
  531. * 2. unconnected_class_hash (optional)
  532. * 3. classLoader callback
  533. * 4. classHandler callback (optional)
  534. **********************************************************************/
  535. Class look_up_class(const char *aClassName, bool includeUnconnected,
  536. bool includeClassHandler)
  537. {
  538. bool includeClassLoader = YES; // class loader cannot be skipped
  539. Class result = nil;
  540. struct objc_class query;
  541. query.name = aClassName;
  542. retry:
  543. if (!result && class_hash) {
  544. // Check ordinary classes
  545. mutex_locker_t lock(classLock);
  546. result = (Class)NXHashGet(class_hash, &query);
  547. }
  548. if (!result && includeUnconnected && unconnected_class_hash) {
  549. // Check not-yet-connected classes
  550. mutex_locker_t lock(classLock);
  551. result = (Class)NXHashGet(unconnected_class_hash, &query);
  552. }
  553. if (!result && includeClassLoader && _objc_classLoader) {
  554. // Try class loader callback
  555. if ((*_objc_classLoader)(aClassName)) {
  556. // Re-try lookup without class loader
  557. includeClassLoader = NO;
  558. goto retry;
  559. }
  560. }
  561. if (!result && includeClassHandler && objc_classHandler) {
  562. // Try class handler callback
  563. if ((*objc_classHandler)(aClassName)) {
  564. // Re-try lookup without class handler or class loader
  565. includeClassLoader = NO;
  566. includeClassHandler = NO;
  567. goto retry;
  568. }
  569. }
  570. return result;
  571. }
  572. /***********************************************************************
  573. * objc_class::isConnected
  574. * Returns TRUE if class cls is connected.
  575. * A connected class has either a connected superclass or a nil superclass,
  576. * and is present in class_hash.
  577. **********************************************************************/
  578. bool objc_class::isConnected()
  579. {
  580. mutex_locker_t lock(classLock);
  581. return NXHashMember(class_hash, this);
  582. }
  583. /***********************************************************************
  584. * pendingClassRefsMapTable. Return a pointer to the lookup table for
  585. * pending class refs.
  586. **********************************************************************/
  587. static inline NXMapTable *pendingClassRefsMapTable(void)
  588. {
  589. // Allocate table if needed
  590. if (!pendingClassRefsMap) {
  591. pendingClassRefsMap = NXCreateMapTable(NXStrValueMapPrototype, 10);
  592. }
  593. // Return table pointer
  594. return pendingClassRefsMap;
  595. }
  596. /***********************************************************************
  597. * pendingSubclassesMapTable. Return a pointer to the lookup table for
  598. * pending subclasses.
  599. **********************************************************************/
  600. static inline NXMapTable *pendingSubclassesMapTable(void)
  601. {
  602. // Allocate table if needed
  603. if (!pendingSubclassesMap) {
  604. pendingSubclassesMap = NXCreateMapTable(NXStrValueMapPrototype, 10);
  605. }
  606. // Return table pointer
  607. return pendingSubclassesMap;
  608. }
  609. /***********************************************************************
  610. * pendClassInstallation
  611. * Finish connecting class cls when its superclass becomes connected.
  612. * Check for multiple pends of the same class because connect_class does not.
  613. **********************************************************************/
  614. static void pendClassInstallation(Class cls, const char *superName)
  615. {
  616. NXMapTable *table;
  617. PendingSubclass *pending;
  618. PendingSubclass *oldList;
  619. PendingSubclass *l;
  620. // Create and/or locate pending class lookup table
  621. table = pendingSubclassesMapTable ();
  622. // Make sure this class isn't already in the pending list.
  623. oldList = (PendingSubclass *)NXMapGet(table, superName);
  624. for (l = oldList; l != nil; l = l->next) {
  625. if (l->subclass == cls) return; // already here, nothing to do
  626. }
  627. // Create entry referring to this class
  628. pending = (PendingSubclass *)malloc(sizeof(PendingSubclass));
  629. pending->subclass = cls;
  630. // Link new entry into head of list of entries for this class
  631. pending->next = oldList;
  632. // (Re)place entry list in the table
  633. NXMapKeyCopyingInsert (table, superName, pending);
  634. }
  635. /***********************************************************************
  636. * pendClassReference
  637. * Fix up a class ref when the class with the given name becomes connected.
  638. **********************************************************************/
  639. static void pendClassReference(Class *ref, const char *className, bool isMeta)
  640. {
  641. NXMapTable *table;
  642. PendingClassRef *pending;
  643. // Create and/or locate pending class lookup table
  644. table = pendingClassRefsMapTable ();
  645. // Create entry containing the class reference
  646. pending = (PendingClassRef *)malloc(sizeof(PendingClassRef));
  647. pending->ref = ref;
  648. if (isMeta) {
  649. pending->ref = (Class *)((uintptr_t)pending->ref | 1);
  650. }
  651. // Link new entry into head of list of entries for this class
  652. pending->next = (PendingClassRef *)NXMapGet(table, className);
  653. // (Re)place entry list in the table
  654. NXMapKeyCopyingInsert (table, className, pending);
  655. if (PrintConnecting) {
  656. _objc_inform("CONNECT: pended reference to class '%s%s' at %p",
  657. className, isMeta ? " (meta)" : "", (void *)ref);
  658. }
  659. }
  660. /***********************************************************************
  661. * resolve_references_to_class
  662. * Fix up any pending class refs to this class.
  663. **********************************************************************/
  664. static void resolve_references_to_class(Class cls)
  665. {
  666. PendingClassRef *pending;
  667. if (!pendingClassRefsMap) return; // no unresolved refs for any class
  668. pending = (PendingClassRef *)NXMapGet(pendingClassRefsMap, cls->name);
  669. if (!pending) return; // no unresolved refs for this class
  670. NXMapKeyFreeingRemove(pendingClassRefsMap, cls->name);
  671. if (PrintConnecting) {
  672. _objc_inform("CONNECT: resolving references to class '%s'", cls->name);
  673. }
  674. while (pending) {
  675. PendingClassRef *next = pending->next;
  676. if (pending->ref) {
  677. bool isMeta = (uintptr_t)pending->ref & 1;
  678. Class *ref =
  679. (Class *)((uintptr_t)pending->ref & ~(uintptr_t)1);
  680. *ref = isMeta ? cls->ISA() : cls;
  681. }
  682. free(pending);
  683. pending = next;
  684. }
  685. if (NXCountMapTable(pendingClassRefsMap) == 0) {
  686. NXFreeMapTable(pendingClassRefsMap);
  687. pendingClassRefsMap = nil;
  688. }
  689. }
  690. /***********************************************************************
  691. * resolve_subclasses_of_class
  692. * Fix up any pending subclasses of this class.
  693. **********************************************************************/
  694. static void resolve_subclasses_of_class(Class cls)
  695. {
  696. PendingSubclass *pending;
  697. if (!pendingSubclassesMap) return; // no unresolved subclasses
  698. pending = (PendingSubclass *)NXMapGet(pendingSubclassesMap, cls->name);
  699. if (!pending) return; // no unresolved subclasses for this class
  700. NXMapKeyFreeingRemove(pendingSubclassesMap, cls->name);
  701. // Destroy the pending table if it's now empty, to save memory.
  702. if (NXCountMapTable(pendingSubclassesMap) == 0) {
  703. NXFreeMapTable(pendingSubclassesMap);
  704. pendingSubclassesMap = nil;
  705. }
  706. if (PrintConnecting) {
  707. _objc_inform("CONNECT: resolving subclasses of class '%s'", cls->name);
  708. }
  709. while (pending) {
  710. PendingSubclass *next = pending->next;
  711. if (pending->subclass) connect_class(pending->subclass);
  712. free(pending);
  713. pending = next;
  714. }
  715. }
  716. /***********************************************************************
  717. * really_connect_class
  718. * Connect cls to superclass supercls unconditionally.
  719. * Also adjust the class hash tables and handle pended subclasses.
  720. *
  721. * This should be called from connect_class() ONLY.
  722. **********************************************************************/
  723. static void really_connect_class(Class cls,
  724. Class supercls)
  725. {
  726. Class oldCls;
  727. // Connect superclass pointers.
  728. set_superclass(cls, supercls, YES);
  729. // Done!
  730. cls->info |= CLS_CONNECTED;
  731. {
  732. mutex_locker_t lock(classLock);
  733. // Update hash tables.
  734. NXHashRemove(unconnected_class_hash, cls);
  735. oldCls = (Class)NXHashInsert(class_hash, cls);
  736. // Delete unconnected_class_hash if it is now empty.
  737. if (NXCountHashTable(unconnected_class_hash) == 0) {
  738. NXFreeHashTable(unconnected_class_hash);
  739. unconnected_class_hash = nil;
  740. }
  741. // No duplicate classes allowed.
  742. // Duplicates should have been rejected by _objc_read_classes_from_image
  743. ASSERT(!oldCls);
  744. }
  745. // Fix up pended class refs to this class, if any
  746. resolve_references_to_class(cls);
  747. // Connect newly-connectable subclasses
  748. resolve_subclasses_of_class(cls);
  749. // Debugging: if this class has ivars, make sure this class's ivars don't
  750. // overlap with its super's. This catches some broken fragile base classes.
  751. // Do not use super->instance_size vs. self->ivar[0] to check this.
  752. // Ivars may be packed across instance_size boundaries.
  753. if (DebugFragileSuperclasses && cls->ivars && cls->ivars->ivar_count) {
  754. Class ivar_cls = supercls;
  755. // Find closest superclass that has some ivars, if one exists.
  756. while (ivar_cls &&
  757. (!ivar_cls->ivars || ivar_cls->ivars->ivar_count == 0))
  758. {
  759. ivar_cls = ivar_cls->superclass;
  760. }
  761. if (ivar_cls) {
  762. // Compare superclass's last ivar to this class's first ivar
  763. old_ivar *super_ivar =
  764. &ivar_cls->ivars->ivar_list[ivar_cls->ivars->ivar_count - 1];
  765. old_ivar *self_ivar =
  766. &cls->ivars->ivar_list[0];
  767. // fixme could be smarter about super's ivar size
  768. if (self_ivar->ivar_offset <= super_ivar->ivar_offset) {
  769. _objc_inform("WARNING: ivars of superclass '%s' and "
  770. "subclass '%s' overlap; superclass may have "
  771. "changed since subclass was compiled",
  772. ivar_cls->name, cls->name);
  773. }
  774. }
  775. }
  776. }
  777. /***********************************************************************
  778. * connect_class
  779. * Connect class cls to its superclasses, if possible.
  780. * If cls becomes connected, move it from unconnected_class_hash
  781. * to connected_class_hash.
  782. * Returns TRUE if cls is connected.
  783. * Returns FALSE if cls could not be connected for some reason
  784. * (missing superclass or still-unconnected superclass)
  785. **********************************************************************/
  786. static bool connect_class(Class cls)
  787. {
  788. if (cls->isConnected()) {
  789. // This class is already connected to its superclass.
  790. // Do nothing.
  791. return TRUE;
  792. }
  793. else if (cls->superclass == nil) {
  794. // This class is a root class.
  795. // Connect it to itself.
  796. if (PrintConnecting) {
  797. _objc_inform("CONNECT: class '%s' now connected (root class)",
  798. cls->name);
  799. }
  800. really_connect_class(cls, nil);
  801. return TRUE;
  802. }
  803. else {
  804. // This class is not a root class and is not yet connected.
  805. // Connect it if its superclass and root class are already connected.
  806. // Otherwise, add this class to the to-be-connected list,
  807. // pending the completion of its superclass and root class.
  808. // At this point, cls->superclass and cls->ISA()->ISA() are still STRINGS
  809. char *supercls_name = (char *)cls->superclass;
  810. Class supercls;
  811. // YES unconnected, YES class handler
  812. if (nil == (supercls = look_up_class(supercls_name, YES, YES))) {
  813. // Superclass does not exist yet.
  814. // pendClassInstallation will handle duplicate pends of this class
  815. pendClassInstallation(cls, supercls_name);
  816. if (PrintConnecting) {
  817. _objc_inform("CONNECT: class '%s' NOT connected (missing super)", cls->name);
  818. }
  819. return FALSE;
  820. }
  821. if (! connect_class(supercls)) {
  822. // Superclass exists but is not yet connected.
  823. // pendClassInstallation will handle duplicate pends of this class
  824. pendClassInstallation(cls, supercls_name);
  825. if (PrintConnecting) {
  826. _objc_inform("CONNECT: class '%s' NOT connected (unconnected super)", cls->name);
  827. }
  828. return FALSE;
  829. }
  830. // Superclass exists and is connected.
  831. // Connect this class to the superclass.
  832. if (PrintConnecting) {
  833. _objc_inform("CONNECT: class '%s' now connected", cls->name);
  834. }
  835. really_connect_class(cls, supercls);
  836. return TRUE;
  837. }
  838. }
  839. /***********************************************************************
  840. * _objc_read_categories_from_image.
  841. * Read all categories from the given image.
  842. * Install them on their parent classes, or register them for later
  843. * installation.
  844. * Returns YES if some method caches now need to be flushed.
  845. **********************************************************************/
  846. static bool _objc_read_categories_from_image (header_info * hi)
  847. {
  848. Module mods;
  849. size_t midx;
  850. bool needFlush = NO;
  851. if (hi->info()->isReplacement()) {
  852. // Ignore any categories in this image
  853. return NO;
  854. }
  855. // Major loop - process all modules in the header
  856. mods = hi->mod_ptr;
  857. // NOTE: The module and category lists are traversed backwards
  858. // to preserve the pre-10.4 processing order. Changing the order
  859. // would have a small chance of introducing binary compatibility bugs.
  860. midx = hi->mod_count;
  861. while (midx-- > 0) {
  862. unsigned int index;
  863. unsigned int total;
  864. // Nothing to do for a module without a symbol table
  865. if (mods[midx].symtab == nil)
  866. continue;
  867. // Total entries in symbol table (class entries followed
  868. // by category entries)
  869. total = mods[midx].symtab->cls_def_cnt +
  870. mods[midx].symtab->cat_def_cnt;
  871. // Minor loop - register all categories from given module
  872. index = total;
  873. while (index-- > mods[midx].symtab->cls_def_cnt) {
  874. old_category *cat = (old_category *)mods[midx].symtab->defs[index];
  875. needFlush |= _objc_register_category(cat, (int)mods[midx].version);
  876. }
  877. }
  878. return needFlush;
  879. }
  880. /***********************************************************************
  881. * _objc_read_classes_from_image.
  882. * Read classes from the given image, perform assorted minor fixups,
  883. * scan for +load implementation.
  884. * Does not connect classes to superclasses.
  885. * Does attach pended categories to the classes.
  886. * Adds all classes to unconnected_class_hash. class_hash is unchanged.
  887. **********************************************************************/
  888. static void _objc_read_classes_from_image(header_info *hi)
  889. {
  890. unsigned int index;
  891. unsigned int midx;
  892. Module mods;
  893. int isBundle = headerIsBundle(hi);
  894. if (hi->info()->isReplacement()) {
  895. // Ignore any classes in this image
  896. return;
  897. }
  898. // class_hash starts small, enough only for libobjc itself.
  899. // If other Objective-C libraries are found, immediately resize
  900. // class_hash, assuming that Foundation and AppKit are about
  901. // to add lots of classes.
  902. {
  903. mutex_locker_t lock(classLock);
  904. if (hi->mhdr() != libobjc_header && _NXHashCapacity(class_hash) < 1024) {
  905. _NXHashRehashToCapacity(class_hash, 1024);
  906. }
  907. }
  908. // Major loop - process all modules in the image
  909. mods = hi->mod_ptr;
  910. for (midx = 0; midx < hi->mod_count; midx += 1)
  911. {
  912. // Skip module containing no classes
  913. if (mods[midx].symtab == nil)
  914. continue;
  915. // Minor loop - process all the classes in given module
  916. for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
  917. {
  918. Class newCls, oldCls;
  919. bool rejected;
  920. // Locate the class description pointer
  921. newCls = (Class)mods[midx].symtab->defs[index];
  922. // Classes loaded from Mach-O bundles can be unloaded later.
  923. // Nothing uses this class yet, so cls->setInfo is not needed.
  924. if (isBundle) newCls->info |= CLS_FROM_BUNDLE;
  925. if (isBundle) newCls->ISA()->info |= CLS_FROM_BUNDLE;
  926. // Use common static empty cache instead of nil
  927. if (newCls->cache == nil)
  928. newCls->cache = (Cache) &_objc_empty_cache;
  929. if (newCls->ISA()->cache == nil)
  930. newCls->ISA()->cache = (Cache) &_objc_empty_cache;
  931. // Set metaclass version
  932. newCls->ISA()->version = mods[midx].version;
  933. // methodLists is nil or a single list, not an array
  934. newCls->info |= CLS_NO_METHOD_ARRAY|CLS_NO_PROPERTY_ARRAY;
  935. newCls->ISA()->info |= CLS_NO_METHOD_ARRAY|CLS_NO_PROPERTY_ARRAY;
  936. // class has no subclasses for cache flushing
  937. newCls->info |= CLS_LEAF;
  938. newCls->ISA()->info |= CLS_LEAF;
  939. if (mods[midx].version >= 6) {
  940. // class structure has ivar_layout and ext fields
  941. newCls->info |= CLS_EXT;
  942. newCls->ISA()->info |= CLS_EXT;
  943. }
  944. // Check for +load implementation before categories are attached
  945. if (_class_hasLoadMethod(newCls)) {
  946. newCls->ISA()->info |= CLS_HAS_LOAD_METHOD;
  947. }
  948. // Install into unconnected_class_hash.
  949. {
  950. mutex_locker_t lock(classLock);
  951. if (future_class_hash) {
  952. Class futureCls = (Class)
  953. NXHashRemove(future_class_hash, newCls);
  954. if (futureCls) {
  955. // Another class structure for this class was already
  956. // prepared by objc_getFutureClass(). Use it instead.
  957. free((char *)futureCls->name);
  958. memcpy(futureCls, newCls, sizeof(objc_class));
  959. setOriginalClassForFutureClass(futureCls, newCls);
  960. newCls = futureCls;
  961. if (NXCountHashTable(future_class_hash) == 0) {
  962. NXFreeHashTable(future_class_hash);
  963. future_class_hash = nil;
  964. }
  965. }
  966. }
  967. if (!unconnected_class_hash) {
  968. unconnected_class_hash =
  969. NXCreateHashTable(classHashPrototype, 128, nil);
  970. }
  971. if ((oldCls = (Class)NXHashGet(class_hash, newCls)) ||
  972. (oldCls = (Class)NXHashGet(unconnected_class_hash, newCls)))
  973. {
  974. // Another class with this name exists. Complain and reject.
  975. inform_duplicate(newCls->name, oldCls, newCls);
  976. rejected = YES;
  977. }
  978. else {
  979. NXHashInsert(unconnected_class_hash, newCls);
  980. rejected = NO;
  981. }
  982. }
  983. if (!rejected) {
  984. // Attach pended categories for this class, if any
  985. resolve_categories_for_class(newCls);
  986. }
  987. }
  988. }
  989. }
  990. /***********************************************************************
  991. * _objc_connect_classes_from_image.
  992. * Connect the classes in the given image to their superclasses,
  993. * or register them for later connection if any superclasses are missing.
  994. **********************************************************************/
  995. static void _objc_connect_classes_from_image(header_info *hi)
  996. {
  997. unsigned int index;
  998. unsigned int midx;
  999. Module mods;
  1000. bool replacement = hi->info()->isReplacement();
  1001. // Major loop - process all modules in the image
  1002. mods = hi->mod_ptr;
  1003. for (midx = 0; midx < hi->mod_count; midx += 1)
  1004. {
  1005. // Skip module containing no classes
  1006. if (mods[midx].symtab == nil)
  1007. continue;
  1008. // Minor loop - process all the classes in given module
  1009. for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
  1010. {
  1011. Class cls = (Class)mods[midx].symtab->defs[index];
  1012. if (! replacement) {
  1013. bool connected;
  1014. Class futureCls = getFutureClassForOriginalClass(cls);
  1015. if (futureCls) {
  1016. // objc_getFutureClass() requested a different class
  1017. // struct. Fix up the original struct's superclass
  1018. // field for [super ...] use, but otherwise perform
  1019. // fixups on the new class struct only.
  1020. const char *super_name = (const char *) cls->superclass;
  1021. if (super_name) cls->superclass = objc_getClass(super_name);
  1022. cls = futureCls;
  1023. }
  1024. connected = connect_class(cls);
  1025. if (connected && callbackFunction) {
  1026. (*callbackFunction)(cls, 0);
  1027. }
  1028. } else {
  1029. // Replacement image - fix up superclass only (#3704817)
  1030. // And metaclass's superclass (#5351107)
  1031. const char *super_name = (const char *) cls->superclass;
  1032. if (super_name) {
  1033. cls->superclass = objc_getClass(super_name);
  1034. // metaclass's superclass is superclass's metaclass
  1035. cls->ISA()->superclass = cls->superclass->ISA();
  1036. } else {
  1037. // Replacement for a root class
  1038. // cls->superclass already nil
  1039. // root metaclass's superclass is root class
  1040. cls->ISA()->superclass = cls;
  1041. }
  1042. }
  1043. }
  1044. }
  1045. }
  1046. /***********************************************************************
  1047. * _objc_map_class_refs_for_image. Convert the class ref entries from
  1048. * a class name string pointer to a class pointer. If the class does
  1049. * not yet exist, the reference is added to a list of pending references
  1050. * to be fixed up at a later date.
  1051. **********************************************************************/
  1052. static void fix_class_ref(Class *ref, const char *name, bool isMeta)
  1053. {
  1054. Class cls;
  1055. // Get pointer to class of this name
  1056. // NO unconnected, YES class loader
  1057. // (real class with weak-missing superclass is unconnected now)
  1058. cls = look_up_class(name, NO, YES);
  1059. if (cls) {
  1060. // Referenced class exists. Fix up the reference.
  1061. *ref = isMeta ? cls->ISA() : cls;
  1062. } else {
  1063. // Referenced class does not exist yet. Insert nil for now
  1064. // (weak-linking) and fix up the reference if the class arrives later.
  1065. pendClassReference (ref, name, isMeta);
  1066. *ref = nil;
  1067. }
  1068. }
  1069. static void _objc_map_class_refs_for_image (header_info * hi)
  1070. {
  1071. Class *cls_refs;
  1072. size_t count;
  1073. unsigned int index;
  1074. // Locate class refs in image
  1075. cls_refs = _getObjcClassRefs (hi, &count);
  1076. if (cls_refs) {
  1077. // Process each class ref
  1078. for (index = 0; index < count; index += 1) {
  1079. // Ref is initially class name char*
  1080. const char *name = (const char *) cls_refs[index];
  1081. if (!name) continue;
  1082. fix_class_ref(&cls_refs[index], name, NO /*never meta*/);
  1083. }
  1084. }
  1085. }
  1086. /***********************************************************************
  1087. * _objc_remove_pending_class_refs_in_image
  1088. * Delete any pending class ref fixups for class refs in the given image,
  1089. * because the image is about to be unloaded.
  1090. **********************************************************************/
  1091. static void removePendingReferences(Class *refs, size_t count)
  1092. {
  1093. Class *end = refs + count;
  1094. if (!refs) return;
  1095. if (!pendingClassRefsMap) return;
  1096. // Search the pending class ref table for class refs in this range.
  1097. // The class refs may have already been stomped with nil,
  1098. // so there's no way to recover the original class name.
  1099. {
  1100. const char *key;
  1101. PendingClassRef *pending;
  1102. NXMapState state = NXInitMapState(pendingClassRefsMap);
  1103. while(NXNextMapState(pendingClassRefsMap, &state,
  1104. (const void **)&key, (const void **)&pending))
  1105. {
  1106. for ( ; pending != nil; pending = pending->next) {
  1107. if (pending->ref >= refs && pending->ref < end) {
  1108. pending->ref = nil;
  1109. }
  1110. }
  1111. }
  1112. }
  1113. }
  1114. static void _objc_remove_pending_class_refs_in_image(header_info *hi)
  1115. {
  1116. Class *cls_refs;
  1117. size_t count;
  1118. // Locate class refs in this image
  1119. cls_refs = _getObjcClassRefs(hi, &count);
  1120. removePendingReferences(cls_refs, count);
  1121. }
  1122. /***********************************************************************
  1123. * map_selrefs. For each selector in the specified array,
  1124. * replace the name pointer with a uniqued selector.
  1125. * If copy is TRUE, all selector data is always copied. This is used
  1126. * for registering selectors from unloadable bundles, so the selector
  1127. * can still be used after the bundle's data segment is unmapped.
  1128. * Returns YES if dst was written to, NO if it was unchanged.
  1129. **********************************************************************/
  1130. static inline void map_selrefs(SEL *sels, size_t count, bool copy)
  1131. {
  1132. size_t index;
  1133. if (!sels) return;
  1134. mutex_locker_t lock(selLock);
  1135. // Process each selector
  1136. for (index = 0; index < count; index += 1)
  1137. {
  1138. SEL sel;
  1139. // Lookup pointer to uniqued string
  1140. sel = sel_registerNameNoLock((const char *) sels[index], copy);
  1141. // Replace this selector with uniqued one (avoid
  1142. // modifying the VM page if this would be a NOP)
  1143. if (sels[index] != sel) {
  1144. sels[index] = sel;
  1145. }
  1146. }
  1147. }
  1148. /***********************************************************************
  1149. * map_method_descs. For each method in the specified method list,
  1150. * replace the name pointer with a uniqued selector.
  1151. * If copy is TRUE, all selector data is always copied. This is used
  1152. * for registering selectors from unloadable bundles, so the selector
  1153. * can still be used after the bundle's data segment is unmapped.
  1154. **********************************************************************/
  1155. static void map_method_descs (struct objc_method_description_list * methods, bool copy)
  1156. {
  1157. int index;
  1158. if (!methods) return;
  1159. mutex_locker_t lock(selLock);
  1160. // Process each method
  1161. for (index = 0; index < methods->count; index += 1)
  1162. {
  1163. struct objc_method_description * method;
  1164. SEL sel;
  1165. // Get method entry to fix up
  1166. method = &methods->list[index];
  1167. // Lookup pointer to uniqued string
  1168. sel = sel_registerNameNoLock((const char *) method->name, copy);
  1169. // Replace this selector with uniqued one (avoid
  1170. // modifying the VM page if this would be a NOP)
  1171. if (method->name != sel)
  1172. method->name = sel;
  1173. }
  1174. }
  1175. /***********************************************************************
  1176. * ext_for_protocol
  1177. * Returns the protocol extension for the given protocol.
  1178. * Returns nil if the protocol has no extension.
  1179. **********************************************************************/
  1180. static old_protocol_ext *ext_for_protocol(old_protocol *proto)
  1181. {
  1182. if (!proto) return nil;
  1183. if (!protocol_ext_map) return nil;
  1184. else return (old_protocol_ext *)NXMapGet(protocol_ext_map, proto);
  1185. }
  1186. /***********************************************************************
  1187. * lookup_method
  1188. * Search a protocol method list for a selector.
  1189. **********************************************************************/
  1190. static struct objc_method_description *
  1191. lookup_method(struct objc_method_description_list *mlist, SEL aSel)
  1192. {
  1193. if (mlist) {
  1194. int i;
  1195. for (i = 0; i < mlist->count; i++) {
  1196. if (mlist->list[i].name == aSel) {
  1197. return mlist->list+i;
  1198. }
  1199. }
  1200. }
  1201. return nil;
  1202. }
  1203. /***********************************************************************
  1204. * lookup_protocol_method
  1205. * Search for a selector in a protocol
  1206. * (and optionally recursively all incorporated protocols)
  1207. **********************************************************************/
  1208. struct objc_method_description *
  1209. lookup_protocol_method(old_protocol *proto, SEL aSel,
  1210. bool isRequiredMethod, bool isInstanceMethod,
  1211. bool recursive)
  1212. {
  1213. struct objc_method_description *m = nil;
  1214. old_protocol_ext *ext;
  1215. if (isRequiredMethod) {
  1216. if (isInstanceMethod) {
  1217. m = lookup_method(proto->instance_methods, aSel);
  1218. } else {
  1219. m = lookup_method(proto->class_methods, aSel);
  1220. }
  1221. } else if ((ext = ext_for_protocol(proto))) {
  1222. if (isInstanceMethod) {
  1223. m = lookup_method(ext->optional_instance_methods, aSel);
  1224. } else {
  1225. m = lookup_method(ext->optional_class_methods, aSel);
  1226. }
  1227. }
  1228. if (!m && recursive && proto->protocol_list) {
  1229. int i;
  1230. for (i = 0; !m && i < proto->protocol_list->count; i++) {
  1231. m = lookup_protocol_method(proto->protocol_list->list[i], aSel,
  1232. isRequiredMethod,isInstanceMethod,true);
  1233. }
  1234. }
  1235. return m;
  1236. }
  1237. /***********************************************************************
  1238. * protocol_getName
  1239. * Returns the name of the given protocol.
  1240. **********************************************************************/
  1241. const char *protocol_getName(Protocol *p)
  1242. {
  1243. old_protocol *proto = oldprotocol(p);
  1244. if (!proto) return "nil";
  1245. return proto->protocol_name;
  1246. }
  1247. /***********************************************************************
  1248. * protocol_getMethodDescription
  1249. * Returns the description of a named method.
  1250. * Searches either required or optional methods.
  1251. * Searches either instance or class methods.
  1252. **********************************************************************/
  1253. struct objc_method_description
  1254. protocol_getMethodDescription(Protocol *p, SEL aSel,
  1255. BOOL isRequiredMethod, BOOL isInstanceMethod)
  1256. {
  1257. struct objc_method_description empty = {nil, nil};
  1258. old_protocol *proto = oldprotocol(p);
  1259. struct objc_method_description *desc;
  1260. if (!proto) return empty;
  1261. desc = lookup_protocol_method(proto, aSel,
  1262. isRequiredMethod, isInstanceMethod, true);
  1263. if (desc) return *desc;
  1264. else return empty;
  1265. }
  1266. /***********************************************************************
  1267. * protocol_copyMethodDescriptionList
  1268. * Returns an array of method descriptions from a protocol.
  1269. * Copies either required or optional methods.
  1270. * Copies either instance or class methods.
  1271. **********************************************************************/
  1272. struct objc_method_description *
  1273. protocol_copyMethodDescriptionList(Protocol *p,
  1274. BOOL isRequiredMethod,
  1275. BOOL isInstanceMethod,
  1276. unsigned int *outCount)
  1277. {
  1278. struct objc_method_description_list *mlist = nil;
  1279. old_protocol *proto = oldprotocol(p);
  1280. old_protocol_ext *ext;
  1281. unsigned int i, count;
  1282. struct objc_method_description *result;
  1283. if (!proto) {
  1284. if (outCount) *outCount = 0;
  1285. return nil;
  1286. }
  1287. if (isRequiredMethod) {
  1288. if (isInstanceMethod) {
  1289. mlist = proto->instance_methods;
  1290. } else {
  1291. mlist = proto->class_methods;
  1292. }
  1293. } else if ((ext = ext_for_protocol(proto))) {
  1294. if (isInstanceMethod) {
  1295. mlist = ext->optional_instance_methods;
  1296. } else {
  1297. mlist = ext->optional_class_methods;
  1298. }
  1299. }
  1300. if (!mlist) {
  1301. if (outCount) *outCount = 0;
  1302. return nil;
  1303. }
  1304. count = mlist->count;
  1305. result = (struct objc_method_description *)
  1306. calloc(count + 1, sizeof(struct objc_method_description));
  1307. for (i = 0; i < count; i++) {
  1308. result[i] = mlist->list[i];
  1309. }
  1310. if (outCount) *outCount = count;
  1311. return result;
  1312. }
  1313. objc_property_t
  1314. protocol_getProperty(Protocol *p, const char *name,
  1315. BOOL isRequiredProperty, BOOL isInstanceProperty)
  1316. {
  1317. old_protocol *proto = oldprotocol(p);
  1318. old_protocol_ext *ext;
  1319. old_protocol_list *proto_list;
  1320. if (!proto || !name) return nil;
  1321. if (!isRequiredProperty) {
  1322. // Only required properties are currently supported
  1323. return nil;
  1324. }
  1325. if ((ext = ext_for_protocol(proto))) {
  1326. old_property_list *plist;
  1327. if (isInstanceProperty) plist = ext->instance_properties;
  1328. else if (ext->hasClassPropertiesField()) plist = ext->class_properties;
  1329. else plist = nil;
  1330. if (plist) {
  1331. uint32_t i;
  1332. for (i = 0; i < plist->count; i++) {
  1333. old_property *prop = property_list_nth(plist, i);
  1334. if (0 == strcmp(name, prop->name)) {
  1335. return (objc_property_t)prop;
  1336. }
  1337. }
  1338. }
  1339. }
  1340. if ((proto_list = proto->protocol_list)) {
  1341. int i;
  1342. for (i = 0; i < proto_list->count; i++) {
  1343. objc_property_t prop =
  1344. protocol_getProperty((Protocol *)proto_list->list[i], name,
  1345. isRequiredProperty, isInstanceProperty);
  1346. if (prop) return prop;
  1347. }
  1348. }
  1349. return nil;
  1350. }
  1351. objc_property_t *
  1352. protocol_copyPropertyList2(Protocol *p, unsigned int *outCount,
  1353. BOOL isRequiredProperty, BOOL isInstanceProperty)
  1354. {
  1355. old_property **result = nil;
  1356. old_protocol_ext *ext;
  1357. old_property_list *plist;
  1358. old_protocol *proto = oldprotocol(p);
  1359. if (! (ext = ext_for_protocol(proto)) || !isRequiredProperty) {
  1360. // Only required properties are currently supported.
  1361. if (outCount) *outCount = 0;
  1362. return nil;
  1363. }
  1364. if (isInstanceProperty) plist = ext->instance_properties;
  1365. else if (ext->hasClassPropertiesField()) plist = ext->class_properties;
  1366. else plist = nil;
  1367. result = copyPropertyList(plist, outCount);
  1368. return (objc_property_t *)result;
  1369. }
  1370. objc_property_t *protocol_copyPropertyList(Protocol *p, unsigned int *outCount)
  1371. {
  1372. return protocol_copyPropertyList2(p, outCount, YES, YES);
  1373. }
  1374. /***********************************************************************
  1375. * protocol_copyProtocolList
  1376. * Copies this protocol's incorporated protocols.
  1377. * Does not copy those protocol's incorporated protocols in turn.
  1378. **********************************************************************/
  1379. Protocol * __unsafe_unretained *
  1380. protocol_copyProtocolList(Protocol *p, unsigned int *outCount)
  1381. {
  1382. unsigned int count = 0;
  1383. Protocol **result = nil;
  1384. old_protocol *proto = oldprotocol(p);
  1385. if (!proto) {
  1386. if (outCount) *outCount = 0;
  1387. return nil;
  1388. }
  1389. if (proto->protocol_list) {
  1390. count = (unsigned int)proto->protocol_list->count;
  1391. }
  1392. if (count > 0) {
  1393. unsigned int i;
  1394. result = (Protocol **)malloc((count+1) * sizeof(Protocol *));
  1395. for (i = 0; i < count; i++) {
  1396. result[i] = (Protocol *)proto->protocol_list->list[i];
  1397. }
  1398. result[i] = nil;
  1399. }
  1400. if (outCount) *outCount = count;
  1401. return result;
  1402. }
  1403. BOOL protocol_conformsToProtocol(Protocol *self_gen, Protocol *other_gen)
  1404. {
  1405. old_protocol *self = oldprotocol(self_gen);
  1406. old_protocol *other = oldprotocol(other_gen);
  1407. if (!self || !other) {
  1408. return NO;
  1409. }
  1410. if (0 == strcmp(self->protocol_name, other->protocol_name)) {
  1411. return YES;
  1412. }
  1413. if (self->protocol_list) {
  1414. int i;
  1415. for (i = 0; i < self->protocol_list->count; i++) {
  1416. old_protocol *proto = self->protocol_list->list[i];
  1417. if (0 == strcmp(other->protocol_name, proto->protocol_name)) {
  1418. return YES;
  1419. }
  1420. if (protocol_conformsToProtocol((Protocol *)proto, other_gen)) {
  1421. return YES;
  1422. }
  1423. }
  1424. }
  1425. return NO;
  1426. }
  1427. BOOL protocol_isEqual(Protocol *self, Protocol *other)
  1428. {
  1429. if (self == other) return YES;
  1430. if (!self || !other) return NO;
  1431. if (!protocol_conformsToProtocol(self, other)) return NO;
  1432. if (!protocol_conformsToProtocol(other, self)) return NO;
  1433. return YES;
  1434. }
  1435. /***********************************************************************
  1436. * _protocol_getMethodTypeEncoding
  1437. * Return the @encode string for the requested protocol method.
  1438. * Returns nil if the compiler did not emit any extended @encode data.
  1439. * Locking: runtimeLock must not be held by the caller
  1440. **********************************************************************/
  1441. const char *
  1442. _protocol_getMethodTypeEncoding(Protocol *proto_gen, SEL sel,
  1443. BOOL isRequiredMethod, BOOL isInstanceMethod)
  1444. {
  1445. old_protocol *proto = oldprotocol(proto_gen);
  1446. if (!proto) return nil;
  1447. old_protocol_ext *ext = ext_for_protocol(proto);
  1448. if (!ext) return nil;
  1449. if (ext->size < offsetof(old_protocol_ext, extendedMethodTypes) + sizeof(ext->extendedMethodTypes)) return nil;
  1450. if (! ext->extendedMethodTypes) return nil;
  1451. struct objc_method_description *m =
  1452. lookup_protocol_method(proto, sel,
  1453. isRequiredMethod, isInstanceMethod, false);
  1454. if (!m) {
  1455. // No method with that name. Search incorporated protocols.
  1456. if (proto->protocol_list) {
  1457. for (int i = 0; i < proto->protocol_list->count; i++) {
  1458. const char *enc =
  1459. _protocol_getMethodTypeEncoding((Protocol *)proto->protocol_list->list[i], sel, isRequiredMethod, isInstanceMethod);
  1460. if (enc) return enc;
  1461. }
  1462. }
  1463. return nil;
  1464. }
  1465. int i = 0;
  1466. if (isRequiredMethod && isInstanceMethod) {
  1467. i += ((uintptr_t)m - (uintptr_t)proto->instance_methods) / sizeof(proto->instance_methods->list[0]);
  1468. goto done;
  1469. } else if (proto->instance_methods) {
  1470. i += proto->instance_methods->count;
  1471. }
  1472. if (isRequiredMethod && !isInstanceMethod) {
  1473. i += ((uintptr_t)m - (uintptr_t)proto->class_methods) / sizeof(proto->class_methods->list[0]);
  1474. goto done;
  1475. } else if (proto->class_methods) {
  1476. i += proto->class_methods->count;
  1477. }
  1478. if (!isRequiredMethod && isInstanceMethod) {
  1479. i += ((uintptr_t)m - (uintptr_t)ext->optional_instance_methods) / sizeof(ext->optional_instance_methods->list[0]);
  1480. goto done;
  1481. } else if (ext->optional_instance_methods) {
  1482. i += ext->optional_instance_methods->count;
  1483. }
  1484. if (!isRequiredMethod && !isInstanceMethod) {
  1485. i += ((uintptr_t)m - (uintptr_t)ext->optional_class_methods) / sizeof(ext->optional_class_methods->list[0]);
  1486. goto done;
  1487. } else if (ext->optional_class_methods) {
  1488. i += ext->optional_class_methods->count;
  1489. }
  1490. done:
  1491. return ext->extendedMethodTypes[i];
  1492. }
  1493. /***********************************************************************
  1494. * objc_allocateProtocol
  1495. * Creates a new protocol. The protocol may not be used until
  1496. * objc_registerProtocol() is called.
  1497. * Returns nil if a protocol with the same name already exists.
  1498. * Locking: acquires classLock
  1499. **********************************************************************/
  1500. Protocol *
  1501. objc_allocateProtocol(const char *name)
  1502. {
  1503. Class cls = objc_getClass("__IncompleteProtocol");
  1504. ASSERT(cls);
  1505. mutex_locker_t lock(classLock);
  1506. if (NXMapGet(protocol_map, name)) return nil;
  1507. old_protocol *result = (old_protocol *)
  1508. calloc(1, sizeof(old_protocol)
  1509. + sizeof(old_protocol_ext));
  1510. old_protocol_ext *ext = (old_protocol_ext *)(result+1);
  1511. result->isa = cls;
  1512. result->protocol_name = strdup(name);
  1513. ext->size = sizeof(old_protocol_ext);
  1514. // fixme reserve name without installing
  1515. NXMapInsert(protocol_ext_map, result, result+1);
  1516. return (Protocol *)result;
  1517. }
  1518. /***********************************************************************
  1519. * objc_registerProtocol
  1520. * Registers a newly-constructed protocol. The protocol is now
  1521. * ready for use and immutable.
  1522. * Locking: acquires classLock
  1523. **********************************************************************/
  1524. void objc_registerProtocol(Protocol *proto_gen)
  1525. {
  1526. old_protocol *proto = oldprotocol(proto_gen);
  1527. Class oldcls = objc_getClass("__IncompleteProtocol");
  1528. Class cls = objc_getClass("Protocol");
  1529. mutex_locker_t lock(classLock);
  1530. if (proto->isa == cls) {
  1531. _objc_inform("objc_registerProtocol: protocol '%s' was already "
  1532. "registered!", proto->protocol_name);
  1533. return;
  1534. }
  1535. if (proto->isa != oldcls) {
  1536. _objc_inform("objc_registerProtocol: protocol '%s' was not allocated "
  1537. "with objc_allocateProtocol!", proto->protocol_name);
  1538. return;
  1539. }
  1540. proto->isa = cls;
  1541. NXMapKeyCopyingInsert(protocol_map, proto->protocol_name, proto);
  1542. }
  1543. /***********************************************************************
  1544. * protocol_addProtocol
  1545. * Adds an incorporated protocol to another protocol.
  1546. * No method enforcement is performed.
  1547. * `proto` must be under construction. `addition` must not.
  1548. * Locking: acquires classLock
  1549. **********************************************************************/
  1550. void
  1551. protocol_addProtocol(Protocol *proto_gen, Protocol *addition_gen)
  1552. {
  1553. old_protocol *proto = oldprotocol(proto_gen);
  1554. old_protocol *addition = oldprotocol(addition_gen);
  1555. Class cls = objc_getClass("__IncompleteProtocol");
  1556. if (!proto_gen) return;
  1557. if (!addition_gen) return;
  1558. mutex_locker_t lock(classLock);
  1559. if (proto->isa != cls) {
  1560. _objc_inform("protocol_addProtocol: modified protocol '%s' is not "
  1561. "under construction!", proto->protocol_name);
  1562. return;
  1563. }
  1564. if (addition->isa == cls) {
  1565. _objc_inform("protocol_addProtocol: added protocol '%s' is still "
  1566. "under construction!", addition->protocol_name);
  1567. return;
  1568. }
  1569. old_protocol_list *protolist = proto->protocol_list;
  1570. if (protolist) {
  1571. size_t size = sizeof(old_protocol_list)
  1572. + protolist->count * sizeof(protolist->list[0]);
  1573. protolist = (old_protocol_list *)
  1574. realloc(protolist, size);
  1575. } else {
  1576. protolist = (old_protocol_list *)
  1577. calloc(1, sizeof(old_protocol_list));
  1578. }
  1579. protolist->list[protolist->count++] = addition;
  1580. proto->protocol_list = protolist;
  1581. }
  1582. /***********************************************************************
  1583. * protocol_addMethodDescription
  1584. * Adds a method to a protocol. The protocol must be under construction.
  1585. * Locking: acquires classLock
  1586. **********************************************************************/
  1587. static void
  1588. _protocol_addMethod(struct objc_method_description_list **list, SEL name, const char *types)
  1589. {
  1590. if (!*list) {
  1591. *list = (struct objc_method_description_list *)
  1592. calloc(sizeof(struct objc_method_description_list), 1);
  1593. } else {
  1594. size_t size = sizeof(struct objc_method_description_list)
  1595. + (*list)->count * sizeof(struct objc_method_description);
  1596. *list = (struct objc_method_description_list *)
  1597. realloc(*list, size);
  1598. }
  1599. struct objc_method_description *desc = &(*list)->list[(*list)->count++];
  1600. desc->name = name;
  1601. desc->types = strdup(types ?: "");
  1602. }
  1603. void
  1604. protocol_addMethodDescription(Protocol *proto_gen, SEL name, const char *types,
  1605. BOOL isRequiredMethod, BOOL isInstanceMethod)
  1606. {
  1607. old_protocol *proto = oldprotocol(proto_gen);
  1608. Class cls = objc_getClass("__IncompleteProtocol");
  1609. if (!proto_gen) return;
  1610. mutex_locker_t lock(classLock);
  1611. if (proto->isa != cls) {
  1612. _objc_inform("protocol_addMethodDescription: protocol '%s' is not "
  1613. "under construction!", proto->protocol_name);
  1614. return;
  1615. }
  1616. if (isRequiredMethod && isInstanceMethod) {
  1617. _protocol_addMethod(&proto->instance_methods, name, types);
  1618. } else if (isRequiredMethod && !isInstanceMethod) {
  1619. _protocol_addMethod(&proto->class_methods, name, types);
  1620. } else if (!isRequiredMethod && isInstanceMethod) {
  1621. old_protocol_ext *ext = (old_protocol_ext *)(proto+1);
  1622. _protocol_addMethod(&ext->optional_instance_methods, name, types);
  1623. } else /* !isRequiredMethod && !isInstanceMethod) */ {
  1624. old_protocol_ext *ext = (old_protocol_ext *)(proto+1);
  1625. _protocol_addMethod(&ext->optional_class_methods, name, types);
  1626. }
  1627. }
  1628. /***********************************************************************
  1629. * protocol_addProperty
  1630. * Adds a property to a protocol. The protocol must be under construction.
  1631. * Locking: acquires classLock
  1632. **********************************************************************/
  1633. static void
  1634. _protocol_addProperty(old_property_list **plist, const char *name,
  1635. const objc_property_attribute_t *attrs,
  1636. unsigned int count)
  1637. {
  1638. if (!*plist) {
  1639. *plist = (old_property_list *)
  1640. calloc(sizeof(old_property_list), 1);
  1641. (*plist)->entsize = sizeof(old_property);
  1642. } else {
  1643. *plist = (old_property_list *)
  1644. realloc(*plist, sizeof(old_property_list)
  1645. + (*plist)->count * (*plist)->entsize);
  1646. }
  1647. old_property *prop = property_list_nth(*plist, (*plist)->count++);
  1648. prop->name = strdup(name);
  1649. prop->attributes = copyPropertyAttributeString(attrs, count);
  1650. }
  1651. void
  1652. protocol_addProperty(Protocol *proto_gen, const char *name,
  1653. const objc_property_attribute_t *attrs,
  1654. unsigned int count,
  1655. BOOL isRequiredProperty, BOOL isInstanceProperty)
  1656. {
  1657. old_protocol *proto = oldprotocol(proto_gen);
  1658. Class cls = objc_getClass("__IncompleteProtocol");
  1659. if (!proto) return;
  1660. if (!name) return;
  1661. mutex_locker_t lock(classLock);
  1662. if (proto->isa != cls) {
  1663. _objc_inform("protocol_addProperty: protocol '%s' is not "
  1664. "under construction!", proto->protocol_name);
  1665. return;
  1666. }
  1667. old_protocol_ext *ext = ext_for_protocol(proto);
  1668. if (isRequiredProperty && isInstanceProperty) {
  1669. _protocol_addProperty(&ext->instance_properties, name, attrs, count);
  1670. }
  1671. else if (isRequiredProperty && !isInstanceProperty) {
  1672. _protocol_addProperty(&ext->class_properties, name, attrs, count);
  1673. }
  1674. // else if (!isRequiredProperty && isInstanceProperty) {
  1675. // _protocol_addProperty(&ext->optional_instance_properties, name, attrs, count);
  1676. //}
  1677. // else /* !isRequiredProperty && !isInstanceProperty) */ {
  1678. // _protocol_addProperty(&ext->optional_class_properties, name, attrs, count);
  1679. //}
  1680. }
  1681. /***********************************************************************
  1682. * _objc_fixup_protocol_objects_for_image. For each protocol in the
  1683. * specified image, selectorize the method names and add to the protocol hash.
  1684. **********************************************************************/
  1685. static bool versionIsExt(uintptr_t version, const char *names, size_t size)
  1686. {
  1687. // CodeWarrior used isa field for string "Protocol"
  1688. // from section __OBJC,__class_names. rdar://4951638
  1689. // gcc (10.4 and earlier) used isa field for version number;
  1690. // the only version number used on Mac OS X was 2.
  1691. // gcc (10.5 and later) uses isa field for ext pointer
  1692. if (version < 4096 /* not PAGE_SIZE */) {
  1693. return NO;
  1694. }
  1695. if (version >= (uintptr_t)names && version < (uintptr_t)(names + size)) {
  1696. return NO;
  1697. }
  1698. return YES;
  1699. }
  1700. static void fix_protocol(old_protocol *proto, Class protocolClass,
  1701. bool isBundle, const char *names, size_t names_size)
  1702. {
  1703. uintptr_t version;
  1704. if (!proto) return;
  1705. version = (uintptr_t)proto->isa;
  1706. // Set the protocol's isa
  1707. proto->isa = protocolClass;
  1708. // Fix up method lists
  1709. // fixme share across duplicates
  1710. map_method_descs (proto->instance_methods, isBundle);
  1711. map_method_descs (proto->class_methods, isBundle);
  1712. // Fix up ext, if any
  1713. if (versionIsExt(version, names, names_size)) {
  1714. old_protocol_ext *ext = (old_protocol_ext *)version;
  1715. NXMapInsert(protocol_ext_map, proto, ext);
  1716. map_method_descs (ext->optional_instance_methods, isBundle);
  1717. map_method_descs (ext->optional_class_methods, isBundle);
  1718. }
  1719. // Record the protocol it if we don't have one with this name yet
  1720. // fixme bundles - copy protocol
  1721. // fixme unloading
  1722. if (!NXMapGet(protocol_map, proto->protocol_name)) {
  1723. NXMapKeyCopyingInsert(protocol_map, proto->protocol_name, proto);
  1724. if (PrintProtocols) {
  1725. _objc_inform("PROTOCOLS: protocol at %p is %s",
  1726. proto, proto->protocol_name);
  1727. }
  1728. } else {
  1729. // duplicate - do nothing
  1730. if (PrintProtocols) {
  1731. _objc_inform("PROTOCOLS: protocol at %p is %s (duplicate)",
  1732. proto, proto->protocol_name);
  1733. }
  1734. }
  1735. }
  1736. static void _objc_fixup_protocol_objects_for_image (header_info * hi)
  1737. {
  1738. Class protocolClass = objc_getClass("Protocol");
  1739. size_t count, i;
  1740. old_protocol **protos;
  1741. int isBundle = headerIsBundle(hi);
  1742. const char *names;
  1743. size_t names_size;
  1744. mutex_locker_t lock(classLock);
  1745. // Allocate the protocol registry if necessary.
  1746. if (!protocol_map) {
  1747. protocol_map =
  1748. NXCreateMapTable(NXStrValueMapPrototype, 32);
  1749. }
  1750. if (!protocol_ext_map) {
  1751. protocol_ext_map =
  1752. NXCreateMapTable(NXPtrValueMapPrototype, 32);
  1753. }
  1754. protos = _getObjcProtocols(hi, &count);
  1755. names = _getObjcClassNames(hi, &names_size);
  1756. for (i = 0; i < count; i++) {
  1757. fix_protocol(protos[i], protocolClass, isBundle, names, names_size);
  1758. }
  1759. }
  1760. /***********************************************************************
  1761. * _objc_fixup_selector_refs. Register all of the selectors in each
  1762. * image, and fix them all up.
  1763. **********************************************************************/
  1764. static void _objc_fixup_selector_refs (const header_info *hi)
  1765. {
  1766. size_t count;
  1767. SEL *sels;
  1768. bool preoptimized = hi->isPreoptimized();
  1769. if (PrintPreopt) {
  1770. if (preoptimized) {
  1771. _objc_inform("PREOPTIMIZATION: honoring preoptimized selectors in %s",
  1772. hi->fname());
  1773. }
  1774. else if (hi->info()->optimizedByDyld()) {
  1775. _objc_inform("PREOPTIMIZATION: IGNORING preoptimized selectors in %s",
  1776. hi->fname());
  1777. }
  1778. }
  1779. if (preoptimized) return;
  1780. sels = _getObjcSelectorRefs (hi, &count);
  1781. map_selrefs(sels, count, headerIsBundle(hi));
  1782. }
  1783. static inline bool _is_threaded() {
  1784. #if TARGET_OS_WIN32
  1785. return YES;
  1786. #else
  1787. return pthread_is_threaded_np() != 0;
  1788. #endif
  1789. }
  1790. #if !TARGET_OS_WIN32
  1791. /***********************************************************************
  1792. * unmap_image
  1793. * Process the given image which is about to be unmapped by dyld.
  1794. * mh is mach_header instead of headerType because that's what
  1795. * dyld_priv.h says even for 64-bit.
  1796. **********************************************************************/
  1797. void
  1798. unmap_image(const char *path __unused, const struct mach_header *mh)
  1799. {
  1800. recursive_mutex_locker_t lock(loadMethodLock);
  1801. unmap_image_nolock(mh);
  1802. }
  1803. /***********************************************************************
  1804. * map_images
  1805. * Process the given images which are being mapped in by dyld.
  1806. * Calls ABI-agnostic code after taking ABI-specific locks.
  1807. **********************************************************************/
  1808. void
  1809. map_images(unsigned count, const char * const paths[],
  1810. const struct mach_header * const mhdrs[])
  1811. {
  1812. recursive_mutex_locker_t lock(loadMethodLock);
  1813. map_images_nolock(count, paths, mhdrs);
  1814. }
  1815. /***********************************************************************
  1816. * load_images
  1817. * Process +load in the given images which are being mapped in by dyld.
  1818. *
  1819. * Locking: acquires classLock and loadMethodLock
  1820. **********************************************************************/
  1821. extern void prepare_load_methods(const headerType *mhdr);
  1822. void
  1823. load_images(const char *path __unused, const struct mach_header *mh)
  1824. {
  1825. recursive_mutex_locker_t lock(loadMethodLock);
  1826. // Discover +load methods
  1827. prepare_load_methods((const headerType *)mh);
  1828. // Call +load methods (without classLock - re-entrant)
  1829. call_load_methods();
  1830. }
  1831. #endif
  1832. /***********************************************************************
  1833. * _read_images
  1834. * Perform metadata processing for hCount images starting with firstNewHeader
  1835. **********************************************************************/
  1836. void _read_images(header_info **hList, uint32_t hCount, int totalClasses, int unoptimizedTotalClass)
  1837. {
  1838. uint32_t i;
  1839. bool categoriesLoaded = NO;
  1840. if (!class_hash) _objc_init_class_hash();
  1841. // Parts of this order are important for correctness or performance.
  1842. // Fix up selector refs from all images.
  1843. for (i = 0; i < hCount; i++) {
  1844. _objc_fixup_selector_refs(hList[i]);
  1845. }
  1846. // Read classes from all images.
  1847. for (i = 0; i < hCount; i++) {
  1848. _objc_read_classes_from_image(hList[i]);
  1849. }
  1850. // Read categories from all images.
  1851. // But not if any other threads are running - they might
  1852. // call a category method before the fixups below are complete.
  1853. if (!_is_threaded()) {
  1854. bool needFlush = NO;
  1855. for (i = 0; i < hCount; i++) {
  1856. needFlush |= _objc_read_categories_from_image(hList[i]);
  1857. }
  1858. if (needFlush) flush_marked_caches();
  1859. categoriesLoaded = YES;
  1860. }
  1861. // Connect classes from all images.
  1862. for (i = 0; i < hCount; i++) {
  1863. _objc_connect_classes_from_image(hList[i]);
  1864. }
  1865. // Fix up class refs, and protocol objects from all images.
  1866. for (i = 0; i < hCount; i++) {
  1867. _objc_map_class_refs_for_image(hList[i]);
  1868. _objc_fixup_protocol_objects_for_image(hList[i]);
  1869. }
  1870. // Read categories from all images.
  1871. // But not if this is the only thread - it's more
  1872. // efficient to attach categories earlier if safe.
  1873. if (!categoriesLoaded) {
  1874. bool needFlush = NO;
  1875. for (i = 0; i < hCount; i++) {
  1876. needFlush |= _objc_read_categories_from_image(hList[i]);
  1877. }
  1878. if (needFlush) flush_marked_caches();
  1879. }
  1880. // Multi-threaded category load MUST BE LAST to avoid a race.
  1881. }
  1882. /***********************************************************************
  1883. * prepare_load_methods
  1884. * Schedule +load for classes in this image, any un-+load-ed
  1885. * superclasses in other images, and any categories in this image.
  1886. **********************************************************************/
  1887. // Recursively schedule +load for cls and any un-+load-ed superclasses.
  1888. // cls must already be connected.
  1889. static void schedule_class_load(Class cls)
  1890. {
  1891. if (cls->info & CLS_LOADED) return;
  1892. if (cls->superclass) schedule_class_load(cls->superclass);
  1893. add_class_to_loadable_list(cls);
  1894. cls->info |= CLS_LOADED;
  1895. }
  1896. void prepare_load_methods(const headerType *mhdr)
  1897. {
  1898. Module mods;
  1899. unsigned int midx;
  1900. header_info *hi;
  1901. for (hi = FirstHeader; hi; hi = hi->getNext()) {
  1902. if (mhdr == hi->mhdr()) break;
  1903. }
  1904. if (!hi) return;
  1905. if (hi->info()->isReplacement()) {
  1906. // Ignore any classes in this image
  1907. return;
  1908. }
  1909. // Major loop - process all modules in the image
  1910. mods = hi->mod_ptr;
  1911. for (midx = 0; midx < hi->mod_count; midx += 1)
  1912. {
  1913. unsigned int index;
  1914. // Skip module containing no classes
  1915. if (mods[midx].symtab == nil)
  1916. continue;
  1917. // Minor loop - process all the classes in given module
  1918. for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
  1919. {
  1920. // Locate the class description pointer
  1921. Class cls = (Class)mods[midx].symtab->defs[index];
  1922. if (cls->info & CLS_CONNECTED) {
  1923. schedule_class_load(cls);
  1924. }
  1925. }
  1926. }
  1927. // Major loop - process all modules in the header
  1928. mods = hi->mod_ptr;
  1929. // NOTE: The module and category lists are traversed backwards
  1930. // to preserve the pre-10.4 processing order. Changing the order
  1931. // would have a small chance of introducing binary compatibility bugs.
  1932. midx = (unsigned int)hi->mod_count;
  1933. while (midx-- > 0) {
  1934. unsigned int index;
  1935. unsigned int total;
  1936. Symtab symtab = mods[midx].symtab;
  1937. // Nothing to do for a module without a symbol table
  1938. if (mods[midx].symtab == nil)
  1939. continue;
  1940. // Total entries in symbol table (class entries followed
  1941. // by category entries)
  1942. total = mods[midx].symtab->cls_def_cnt +
  1943. mods[midx].symtab->cat_def_cnt;
  1944. // Minor loop - register all categories from given module
  1945. index = total;
  1946. while (index-- > mods[midx].symtab->cls_def_cnt) {
  1947. old_category *cat = (old_category *)symtab->defs[index];
  1948. add_category_to_loadable_list((Category)cat);
  1949. }
  1950. }
  1951. }
  1952. #if TARGET_OS_WIN32
  1953. void unload_class(Class cls)
  1954. {
  1955. }
  1956. #else
  1957. /***********************************************************************
  1958. * _objc_remove_classes_in_image
  1959. * Remove all classes in the given image from the runtime, because
  1960. * the image is about to be unloaded.
  1961. * Things to clean up:
  1962. * class_hash
  1963. * unconnected_class_hash
  1964. * pending subclasses list (only if class is still unconnected)
  1965. * loadable class list
  1966. * class's method caches
  1967. * class refs in all other images
  1968. **********************************************************************/
  1969. // Re-pend any class references in refs that point into [start..end)
  1970. static void rependClassReferences(Class *refs, size_t count,
  1971. uintptr_t start, uintptr_t end)
  1972. {
  1973. size_t i;
  1974. if (!refs) return;
  1975. // Process each class ref
  1976. for (i = 0; i < count; i++) {
  1977. if ((uintptr_t)(refs[i]) >= start && (uintptr_t)(refs[i]) < end) {
  1978. pendClassReference(&refs[i], refs[i]->name,
  1979. refs[i]->info & CLS_META);
  1980. refs[i] = nil;
  1981. }
  1982. }
  1983. }
  1984. void try_free(const void *p)
  1985. {
  1986. if (p && malloc_size(p)) free((void *)p);
  1987. }
  1988. // Deallocate all memory in a method list
  1989. static void unload_mlist(old_method_list *mlist)
  1990. {
  1991. int i;
  1992. for (i = 0; i < mlist->method_count; i++) {
  1993. try_free(mlist->method_list[i].method_types);
  1994. }
  1995. try_free(mlist);
  1996. }
  1997. static void unload_property_list(old_property_list *proplist)
  1998. {
  1999. uint32_t i;
  2000. if (!proplist) return;
  2001. for (i = 0; i < proplist->count; i++) {
  2002. old_property *prop = property_list_nth(proplist, i);
  2003. try_free(prop->name);
  2004. try_free(prop->attributes);
  2005. }
  2006. try_free(proplist);
  2007. }
  2008. // Deallocate all memory in a class.
  2009. void unload_class(Class cls)
  2010. {
  2011. // Free method cache
  2012. // This dereferences the cache contents; do this before freeing methods
  2013. if (cls->cache && cls->cache != &_objc_empty_cache) {
  2014. _cache_free(cls->cache);
  2015. }
  2016. // Free ivar lists
  2017. if (cls->ivars) {
  2018. int i;
  2019. for (i = 0; i < cls->ivars->ivar_count; i++) {
  2020. try_free(cls->ivars->ivar_list[i].ivar_name);
  2021. try_free(cls->ivars->ivar_list[i].ivar_type);
  2022. }
  2023. try_free(cls->ivars);
  2024. }
  2025. // Free fixed-up method lists and method list array
  2026. if (cls->methodLists) {
  2027. // more than zero method lists
  2028. if (cls->info & CLS_NO_METHOD_ARRAY) {
  2029. // one method list
  2030. unload_mlist((old_method_list *)cls->methodLists);
  2031. }
  2032. else {
  2033. // more than one method list
  2034. old_method_list **mlistp;
  2035. for (mlistp = cls->methodLists;
  2036. *mlistp != nil && *mlistp != END_OF_METHODS_LIST;
  2037. mlistp++)
  2038. {
  2039. unload_mlist(*mlistp);
  2040. }
  2041. free(cls->methodLists);
  2042. }
  2043. }
  2044. // Free protocol list
  2045. old_protocol_list *protos = cls->protocols;
  2046. while (protos) {
  2047. old_protocol_list *dead = protos;
  2048. protos = protos->next;
  2049. try_free(dead);
  2050. }
  2051. if ((cls->info & CLS_EXT)) {
  2052. if (cls->ext) {
  2053. // Free property lists and property list array
  2054. if (cls->ext->propertyLists) {
  2055. // more than zero property lists
  2056. if (cls->info & CLS_NO_PROPERTY_ARRAY) {
  2057. // one property list
  2058. old_property_list *proplist =
  2059. (old_property_list *)cls->ext->propertyLists;
  2060. unload_property_list(proplist);
  2061. } else {
  2062. // more than one property list
  2063. old_property_list **plistp;
  2064. for (plistp = cls->ext->propertyLists;
  2065. *plistp != nil;
  2066. plistp++)
  2067. {
  2068. unload_property_list(*plistp);
  2069. }
  2070. try_free(cls->ext->propertyLists);
  2071. }
  2072. }
  2073. // Free weak ivar layout
  2074. try_free(cls->ext->weak_ivar_layout);
  2075. // Free ext
  2076. try_free(cls->ext);
  2077. }
  2078. // Free non-weak ivar layout
  2079. try_free(cls->ivar_layout);
  2080. }
  2081. // Free class name
  2082. try_free(cls->name);
  2083. // Free cls
  2084. try_free(cls);
  2085. }
  2086. static void _objc_remove_classes_in_image(header_info *hi)
  2087. {
  2088. unsigned int index;
  2089. unsigned int midx;
  2090. Module mods;
  2091. mutex_locker_t lock(classLock);
  2092. // Major loop - process all modules in the image
  2093. mods = hi->mod_ptr;
  2094. for (midx = 0; midx < hi->mod_count; midx += 1)
  2095. {
  2096. // Skip module containing no classes
  2097. if (mods[midx].symtab == nil)
  2098. continue;
  2099. // Minor loop - process all the classes in given module
  2100. for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
  2101. {
  2102. Class cls;
  2103. // Locate the class description pointer
  2104. cls = (Class)mods[midx].symtab->defs[index];
  2105. // Remove from loadable class list, if present
  2106. remove_class_from_loadable_list(cls);
  2107. // Remove from unconnected_class_hash and pending subclasses
  2108. if (unconnected_class_hash && NXHashMember(unconnected_class_hash, cls)) {
  2109. NXHashRemove(unconnected_class_hash, cls);
  2110. if (pendingSubclassesMap) {
  2111. // Find this class in its superclass's pending list
  2112. char *supercls_name = (char *)cls->superclass;
  2113. PendingSubclass *pending = (PendingSubclass *)
  2114. NXMapGet(pendingSubclassesMap, supercls_name);
  2115. for ( ; pending != nil; pending = pending->next) {
  2116. if (pending->subclass == cls) {
  2117. pending->subclass = Nil;
  2118. break;
  2119. }
  2120. }
  2121. }
  2122. }
  2123. // Remove from class_hash
  2124. NXHashRemove(class_hash, cls);
  2125. // Free heap memory pointed to by the class
  2126. unload_class(cls->ISA());
  2127. unload_class(cls);
  2128. }
  2129. }
  2130. // Search all other images for class refs that point back to this range.
  2131. // Un-fix and re-pend any such class refs.
  2132. // Get the location of the dying image's __OBJC segment
  2133. uintptr_t seg;
  2134. unsigned long seg_size;
  2135. seg = (uintptr_t)getsegmentdata(hi->mhdr(), "__OBJC", &seg_size);
  2136. header_info *other_hi;
  2137. for (other_hi = FirstHeader; other_hi != nil; other_hi = other_hi->getNext()) {
  2138. Class *other_refs;
  2139. size_t count;
  2140. if (other_hi == hi) continue; // skip the image being unloaded
  2141. // Fix class refs in the other image
  2142. other_refs = _getObjcClassRefs(other_hi, &count);
  2143. rependClassReferences(other_refs, count, seg, seg+seg_size);
  2144. }
  2145. }
  2146. /***********************************************************************
  2147. * _objc_remove_categories_in_image
  2148. * Remove all categories in the given image from the runtime, because
  2149. * the image is about to be unloaded.
  2150. * Things to clean up:
  2151. * unresolved category list
  2152. * loadable category list
  2153. **********************************************************************/
  2154. static void _objc_remove_categories_in_image(header_info *hi)
  2155. {
  2156. Module mods;
  2157. unsigned int midx;
  2158. // Major loop - process all modules in the header
  2159. mods = hi->mod_ptr;
  2160. for (midx = 0; midx < hi->mod_count; midx++) {
  2161. unsigned int index;
  2162. unsigned int total;
  2163. Symtab symtab = mods[midx].symtab;
  2164. // Nothing to do for a module without a symbol table
  2165. if (symtab == nil) continue;
  2166. // Total entries in symbol table (class entries followed
  2167. // by category entries)
  2168. total = symtab->cls_def_cnt + symtab->cat_def_cnt;
  2169. // Minor loop - check all categories from given module
  2170. for (index = symtab->cls_def_cnt; index < total; index++) {
  2171. old_category *cat = (old_category *)symtab->defs[index];
  2172. // Clean up loadable category list
  2173. remove_category_from_loadable_list((Category)cat);
  2174. // Clean up category_hash
  2175. if (category_hash) {
  2176. _objc_unresolved_category *cat_entry = (_objc_unresolved_category *)NXMapGet(category_hash, cat->class_name);
  2177. for ( ; cat_entry != nil; cat_entry = cat_entry->next) {
  2178. if (cat_entry->cat == cat) {
  2179. cat_entry->cat = nil;
  2180. break;
  2181. }
  2182. }
  2183. }
  2184. }
  2185. }
  2186. }
  2187. /***********************************************************************
  2188. * unload_paranoia
  2189. * Various paranoid debugging checks that look for poorly-behaving
  2190. * unloadable bundles.
  2191. * Called by _objc_unmap_image when OBJC_UNLOAD_DEBUG is set.
  2192. **********************************************************************/
  2193. static void unload_paranoia(header_info *hi)
  2194. {
  2195. // Get the location of the dying image's __OBJC segment
  2196. uintptr_t seg;
  2197. unsigned long seg_size;
  2198. seg = (uintptr_t)getsegmentdata(hi->mhdr(), "__OBJC", &seg_size);
  2199. _objc_inform("UNLOAD DEBUG: unloading image '%s' [%p..%p]",
  2200. hi->fname(), (void *)seg, (void*)(seg+seg_size));
  2201. mutex_locker_t lock(classLock);
  2202. // Make sure the image contains no categories on surviving classes.
  2203. {
  2204. Module mods;
  2205. unsigned int midx;
  2206. // Major loop - process all modules in the header
  2207. mods = hi->mod_ptr;
  2208. for (midx = 0; midx < hi->mod_count; midx++) {
  2209. unsigned int index;
  2210. unsigned int total;
  2211. Symtab symtab = mods[midx].symtab;
  2212. // Nothing to do for a module without a symbol table
  2213. if (symtab == nil) continue;
  2214. // Total entries in symbol table (class entries followed
  2215. // by category entries)
  2216. total = symtab->cls_def_cnt + symtab->cat_def_cnt;
  2217. // Minor loop - check all categories from given module
  2218. for (index = symtab->cls_def_cnt; index < total; index++) {
  2219. old_category *cat = (old_category *)symtab->defs[index];
  2220. struct objc_class query;
  2221. query.name = cat->class_name;
  2222. if (NXHashMember(class_hash, &query)) {
  2223. _objc_inform("UNLOAD DEBUG: dying image contains category '%s(%s)' on surviving class '%s'!", cat->class_name, cat->category_name, cat->class_name);
  2224. }
  2225. }
  2226. }
  2227. }
  2228. // Make sure no surviving class is in the dying image.
  2229. // Make sure no surviving class has a superclass in the dying image.
  2230. // fixme check method implementations too
  2231. {
  2232. Class cls;
  2233. NXHashState state;
  2234. state = NXInitHashState(class_hash);
  2235. while (NXNextHashState(class_hash, &state, (void **)&cls)) {
  2236. if ((vm_address_t)cls >= seg &&
  2237. (vm_address_t)cls < seg+seg_size)
  2238. {
  2239. _objc_inform("UNLOAD DEBUG: dying image contains surviving class '%s'!", cls->name);
  2240. }
  2241. if ((vm_address_t)cls->superclass >= seg &&
  2242. (vm_address_t)cls->superclass < seg+seg_size)
  2243. {
  2244. _objc_inform("UNLOAD DEBUG: dying image contains superclass '%s' of surviving class '%s'!", cls->superclass->name, cls->name);
  2245. }
  2246. }
  2247. }
  2248. }
  2249. /***********************************************************************
  2250. * _unload_image
  2251. * Only handles MH_BUNDLE for now.
  2252. * Locking: loadMethodLock acquired by unmap_image
  2253. **********************************************************************/
  2254. void _unload_image(header_info *hi)
  2255. {
  2256. loadMethodLock.assertLocked();
  2257. // Cleanup:
  2258. // Remove image's classes from the class list and free auxiliary data.
  2259. // Remove image's unresolved or loadable categories and free auxiliary data
  2260. // Remove image's unresolved class refs.
  2261. _objc_remove_classes_in_image(hi);
  2262. _objc_remove_categories_in_image(hi);
  2263. _objc_remove_pending_class_refs_in_image(hi);
  2264. if (hi->proto_refs) try_free(hi->proto_refs);
  2265. // Perform various debugging checks if requested.
  2266. if (DebugUnload) unload_paranoia(hi);
  2267. }
  2268. #endif
  2269. /***********************************************************************
  2270. * objc_addClass. Add the specified class to the table of known classes,
  2271. * after doing a little verification and fixup.
  2272. **********************************************************************/
  2273. void objc_addClass (Class cls)
  2274. {
  2275. OBJC_WARN_DEPRECATED;
  2276. // Synchronize access to hash table
  2277. mutex_locker_t lock(classLock);
  2278. // Make sure both the class and the metaclass have caches!
  2279. // Clear all bits of the info fields except CLS_CLASS and CLS_META.
  2280. // Normally these bits are already clear but if someone tries to cons
  2281. // up their own class on the fly they might need to be cleared.
  2282. if (cls->cache == nil) {
  2283. cls->cache = (Cache) &_objc_empty_cache;
  2284. cls->info = CLS_CLASS;
  2285. }
  2286. if (cls->ISA()->cache == nil) {
  2287. cls->ISA()->cache = (Cache) &_objc_empty_cache;
  2288. cls->ISA()->info = CLS_META;
  2289. }
  2290. // methodLists should be:
  2291. // 1. nil (Tiger and later only)
  2292. // 2. A -1 terminated method list array
  2293. // In either case, CLS_NO_METHOD_ARRAY remains clear.
  2294. // If the user manipulates the method list directly,
  2295. // they must use the magic private format.
  2296. // Add the class to the table
  2297. (void) NXHashInsert (class_hash, cls);
  2298. // Superclass is no longer a leaf for cache flushing
  2299. if (cls->superclass && (cls->superclass->info & CLS_LEAF)) {
  2300. cls->superclass->clearInfo(CLS_LEAF);
  2301. cls->superclass->ISA()->clearInfo(CLS_LEAF);
  2302. }
  2303. }
  2304. /***********************************************************************
  2305. * _objcTweakMethodListPointerForClass.
  2306. * Change the class's method list pointer to a method list array.
  2307. * Does nothing if the method list pointer is already a method list array.
  2308. * If the class is currently in use, methodListLock must be held by the caller.
  2309. **********************************************************************/
  2310. static void _objcTweakMethodListPointerForClass(Class cls)
  2311. {
  2312. old_method_list * originalList;
  2313. const int initialEntries = 4;
  2314. size_t mallocSize;
  2315. old_method_list ** ptr;
  2316. // Do nothing if methodLists is already an array.
  2317. if (cls->methodLists && !(cls->info & CLS_NO_METHOD_ARRAY)) return;
  2318. // Remember existing list
  2319. originalList = (old_method_list *) cls->methodLists;
  2320. // Allocate and zero a method list array
  2321. mallocSize = sizeof(old_method_list *) * initialEntries;
  2322. ptr = (old_method_list **) calloc(1, mallocSize);
  2323. // Insert the existing list into the array
  2324. ptr[initialEntries - 1] = END_OF_METHODS_LIST;
  2325. ptr[0] = originalList;
  2326. // Replace existing list with array
  2327. cls->methodLists = ptr;
  2328. cls->clearInfo(CLS_NO_METHOD_ARRAY);
  2329. }
  2330. /***********************************************************************
  2331. * _objc_insertMethods.
  2332. * Adds methods to a class.
  2333. * Does not flush any method caches.
  2334. * Does not take any locks.
  2335. * If the class is already in use, use class_addMethods() instead.
  2336. **********************************************************************/
  2337. void _objc_insertMethods(Class cls, old_method_list *mlist, old_category *cat)
  2338. {
  2339. old_method_list ***list;
  2340. old_method_list **ptr;
  2341. ptrdiff_t endIndex;
  2342. size_t oldSize;
  2343. size_t newSize;
  2344. if (!cls->methodLists) {
  2345. // cls has no methods - simply use this method list
  2346. cls->methodLists = (old_method_list **)mlist;
  2347. cls->setInfo(CLS_NO_METHOD_ARRAY);
  2348. return;
  2349. }
  2350. // Log any existing methods being replaced
  2351. if (PrintReplacedMethods) {
  2352. int i;
  2353. for (i = 0; i < mlist->method_count; i++) {
  2354. extern IMP findIMPInClass(Class cls, SEL sel);
  2355. SEL sel = sel_registerName((char *)mlist->method_list[i].method_name);
  2356. IMP newImp = mlist->method_list[i].method_imp;
  2357. IMP oldImp;
  2358. if ((oldImp = findIMPInClass(cls, sel))) {
  2359. logReplacedMethod(cls->name, sel, ISMETA(cls),
  2360. cat ? cat->category_name : nil,
  2361. oldImp, newImp);
  2362. }
  2363. }
  2364. }
  2365. // Create method list array if necessary
  2366. _objcTweakMethodListPointerForClass(cls);
  2367. list = &cls->methodLists;
  2368. // Locate unused entry for insertion point
  2369. ptr = *list;
  2370. while ((*ptr != 0) && (*ptr != END_OF_METHODS_LIST))
  2371. ptr += 1;
  2372. // If array is full, add to it
  2373. if (*ptr == END_OF_METHODS_LIST)
  2374. {
  2375. // Calculate old and new dimensions
  2376. endIndex = ptr - *list;
  2377. oldSize = (endIndex + 1) * sizeof(void *);
  2378. newSize = oldSize + sizeof(old_method_list *); // only increase by 1
  2379. // Grow the method list array by one.
  2380. *list = (old_method_list **)realloc(*list, newSize);
  2381. // Zero out addition part of new array
  2382. bzero (&((*list)[endIndex]), newSize - oldSize);
  2383. // Place new end marker
  2384. (*list)[(newSize/sizeof(void *)) - 1] = END_OF_METHODS_LIST;
  2385. // Insertion point corresponds to old array end
  2386. ptr = &((*list)[endIndex]);
  2387. }
  2388. // Right shift existing entries by one
  2389. bcopy (*list, (*list) + 1, (uint8_t *)ptr - (uint8_t *)*list);
  2390. // Insert at method list at beginning of array
  2391. **list = mlist;
  2392. }
  2393. /***********************************************************************
  2394. * _objc_removeMethods.
  2395. * Remove methods from a class.
  2396. * Does not take any locks.
  2397. * Does not flush any method caches.
  2398. * If the class is currently in use, use class_removeMethods() instead.
  2399. **********************************************************************/
  2400. void _objc_removeMethods(Class cls, old_method_list *mlist)
  2401. {
  2402. old_method_list ***list;
  2403. old_method_list **ptr;
  2404. if (cls->methodLists == nil) {
  2405. // cls has no methods
  2406. return;
  2407. }
  2408. if (cls->methodLists == (old_method_list **)mlist) {
  2409. // mlist is the class's only method list - erase it
  2410. cls->methodLists = nil;
  2411. return;
  2412. }
  2413. if (cls->info & CLS_NO_METHOD_ARRAY) {
  2414. // cls has only one method list, and this isn't it - do nothing
  2415. return;
  2416. }
  2417. // cls has a method list array - search it
  2418. list = &cls->methodLists;
  2419. // Locate list in the array
  2420. ptr = *list;
  2421. while (*ptr != mlist) {
  2422. // fix for radar # 2538790
  2423. if ( *ptr == END_OF_METHODS_LIST ) return;
  2424. ptr += 1;
  2425. }
  2426. // Remove this entry
  2427. *ptr = 0;
  2428. // Left shift the following entries
  2429. while (*(++ptr) != END_OF_METHODS_LIST)
  2430. *(ptr-1) = *ptr;
  2431. *(ptr-1) = 0;
  2432. }
  2433. /***********************************************************************
  2434. * _objc_add_category. Install the specified category's methods and
  2435. * protocols into the class it augments.
  2436. * The class is assumed not to be in use yet: no locks are taken and
  2437. * no method caches are flushed.
  2438. **********************************************************************/
  2439. static inline void _objc_add_category(Class cls, old_category *category, int version)
  2440. {
  2441. if (PrintConnecting) {
  2442. _objc_inform("CONNECT: attaching category '%s (%s)'", cls->name, category->category_name);
  2443. }
  2444. // Augment instance methods
  2445. if (category->instance_methods)
  2446. _objc_insertMethods (cls, category->instance_methods, category);
  2447. // Augment class methods
  2448. if (category->class_methods)
  2449. _objc_insertMethods (cls->ISA(), category->class_methods, category);
  2450. // Augment protocols
  2451. if ((version >= 5) && category->protocols)
  2452. {
  2453. if (cls->ISA()->version >= 5)
  2454. {
  2455. category->protocols->next = cls->protocols;
  2456. cls->protocols = category->protocols;
  2457. cls->ISA()->protocols = category->protocols;
  2458. }
  2459. else
  2460. {
  2461. _objc_inform ("unable to add protocols from category %s...\n", category->category_name);
  2462. _objc_inform ("class `%s' must be recompiled\n", category->class_name);
  2463. }
  2464. }
  2465. // Augment instance properties
  2466. if (version >= 7 && category->instance_properties) {
  2467. if (cls->ISA()->version >= 6) {
  2468. _class_addProperties(cls, category->instance_properties);
  2469. } else {
  2470. _objc_inform ("unable to add instance properties from category %s...\n", category->category_name);
  2471. _objc_inform ("class `%s' must be recompiled\n", category->class_name);
  2472. }
  2473. }
  2474. // Augment class properties
  2475. if (version >= 7 && category->hasClassPropertiesField() &&
  2476. category->class_properties)
  2477. {
  2478. if (cls->ISA()->version >= 6) {
  2479. _class_addProperties(cls->ISA(), category->class_properties);
  2480. } else {
  2481. _objc_inform ("unable to add class properties from category %s...\n", category->category_name);
  2482. _objc_inform ("class `%s' must be recompiled\n", category->class_name);
  2483. }
  2484. }
  2485. }
  2486. /***********************************************************************
  2487. * _objc_add_category_flush_caches. Install the specified category's
  2488. * methods into the class it augments, and flush the class' method cache.
  2489. * Return YES if some method caches now need to be flushed.
  2490. **********************************************************************/
  2491. static bool _objc_add_category_flush_caches(Class cls, old_category *category, int version)
  2492. {
  2493. bool needFlush = NO;
  2494. // Install the category's methods into its intended class
  2495. {
  2496. mutex_locker_t lock(methodListLock);
  2497. _objc_add_category (cls, category, version);
  2498. }
  2499. // Queue for cache flushing so category's methods can get called
  2500. if (category->instance_methods) {
  2501. cls->setInfo(CLS_FLUSH_CACHE);
  2502. needFlush = YES;
  2503. }
  2504. if (category->class_methods) {
  2505. cls->ISA()->setInfo(CLS_FLUSH_CACHE);
  2506. needFlush = YES;
  2507. }
  2508. return needFlush;
  2509. }
  2510. /***********************************************************************
  2511. * reverse_cat
  2512. * Reverse the given linked list of pending categories.
  2513. * The pending category list is built backwards, and needs to be
  2514. * reversed before actually attaching the categories to a class.
  2515. * Returns the head of the new linked list.
  2516. **********************************************************************/
  2517. static _objc_unresolved_category *reverse_cat(_objc_unresolved_category *cat)
  2518. {
  2519. _objc_unresolved_category *prev;
  2520. _objc_unresolved_category *cur;
  2521. _objc_unresolved_category *ahead;
  2522. if (!cat) return nil;
  2523. prev = nil;
  2524. cur = cat;
  2525. ahead = cat->next;
  2526. while (cur) {
  2527. ahead = cur->next;
  2528. cur->next = prev;
  2529. prev = cur;
  2530. cur = ahead;
  2531. }
  2532. return prev;
  2533. }
  2534. /***********************************************************************
  2535. * resolve_categories_for_class.
  2536. * Install all existing categories intended for the specified class.
  2537. * cls must be a true class and not a metaclass.
  2538. **********************************************************************/
  2539. static void resolve_categories_for_class(Class cls)
  2540. {
  2541. _objc_unresolved_category * pending;
  2542. _objc_unresolved_category * next;
  2543. // Nothing to do if there are no categories at all
  2544. if (!category_hash) return;
  2545. // Locate and remove first element in category list
  2546. // associated with this class
  2547. pending = (_objc_unresolved_category *)
  2548. NXMapKeyFreeingRemove (category_hash, cls->name);
  2549. // Traverse the list of categories, if any, registered for this class
  2550. // The pending list is built backwards. Reverse it and walk forwards.
  2551. pending = reverse_cat(pending);
  2552. while (pending) {
  2553. if (pending->cat) {
  2554. // Install the category
  2555. // use the non-flush-cache version since we are only
  2556. // called from the class intialization code
  2557. _objc_add_category(cls, pending->cat, (int)pending->version);
  2558. }
  2559. // Delink and reclaim this registration
  2560. next = pending->next;
  2561. free(pending);
  2562. pending = next;
  2563. }
  2564. }
  2565. /***********************************************************************
  2566. * _objc_resolve_categories_for_class.
  2567. * Public version of resolve_categories_for_class. This was
  2568. * exported pre-10.4 for Omni et al. to workaround a problem
  2569. * with too-lazy category attachment.
  2570. * cls should be a class, but this function can also cope with metaclasses.
  2571. **********************************************************************/
  2572. void _objc_resolve_categories_for_class(Class cls)
  2573. {
  2574. // If cls is a metaclass, get the class.
  2575. // resolve_categories_for_class() requires a real class to work correctly.
  2576. if (ISMETA(cls)) {
  2577. if (strncmp(cls->name, "_%", 2) == 0) {
  2578. // Posee's meta's name is smashed and isn't in the class_hash,
  2579. // so objc_getClass doesn't work.
  2580. const char *baseName = strchr(cls->name, '%'); // get posee's real name
  2581. cls = objc_getClass(baseName);
  2582. } else {
  2583. cls = objc_getClass(cls->name);
  2584. }
  2585. }
  2586. resolve_categories_for_class(cls);
  2587. }
  2588. /***********************************************************************
  2589. * _objc_register_category.
  2590. * Process a category read from an image.
  2591. * If the category's class exists, attach the category immediately.
  2592. * Classes that need cache flushing are marked but not flushed.
  2593. * If the category's class does not exist yet, pend the category for
  2594. * later attachment. Pending categories are attached in the order
  2595. * they were discovered.
  2596. * Returns YES if some method caches now need to be flushed.
  2597. **********************************************************************/
  2598. static bool _objc_register_category(old_category *cat, int version)
  2599. {
  2600. _objc_unresolved_category * new_cat;
  2601. _objc_unresolved_category * old;
  2602. Class theClass;
  2603. // If the category's class exists, attach the category.
  2604. if ((theClass = objc_lookUpClass(cat->class_name))) {
  2605. return _objc_add_category_flush_caches(theClass, cat, version);
  2606. }
  2607. // If the category's class exists but is unconnected,
  2608. // then attach the category to the class but don't bother
  2609. // flushing any method caches (because they must be empty).
  2610. // YES unconnected, NO class_handler
  2611. if ((theClass = look_up_class(cat->class_name, YES, NO))) {
  2612. _objc_add_category(theClass, cat, version);
  2613. return NO;
  2614. }
  2615. // Category's class does not exist yet.
  2616. // Save the category for later attachment.
  2617. if (PrintConnecting) {
  2618. _objc_inform("CONNECT: pending category '%s (%s)'", cat->class_name, cat->category_name);
  2619. }
  2620. // Create category lookup table if needed
  2621. if (!category_hash)
  2622. category_hash = NXCreateMapTable(NXStrValueMapPrototype, 128);
  2623. // Locate an existing list of categories, if any, for the class.
  2624. old = (_objc_unresolved_category *)
  2625. NXMapGet (category_hash, cat->class_name);
  2626. // Register the category to be fixed up later.
  2627. // The category list is built backwards, and is reversed again
  2628. // by resolve_categories_for_class().
  2629. new_cat = (_objc_unresolved_category *)
  2630. malloc(sizeof(_objc_unresolved_category));
  2631. new_cat->next = old;
  2632. new_cat->cat = cat;
  2633. new_cat->version = version;
  2634. (void) NXMapKeyCopyingInsert (category_hash, cat->class_name, new_cat);
  2635. return NO;
  2636. }
  2637. const char **objc_copyImageNames(unsigned int *outCount)
  2638. {
  2639. header_info *hi;
  2640. int count = 0;
  2641. int max = 0;
  2642. for (hi = FirstHeader; hi != nil; hi = hi->getNext()) {
  2643. max++;
  2644. }
  2645. #if TARGET_OS_WIN32
  2646. const TCHAR **names = (const TCHAR **)calloc(max+1, sizeof(TCHAR *));
  2647. #else
  2648. const char **names = (const char **)calloc(max+1, sizeof(char *));
  2649. #endif
  2650. for (hi = FirstHeader; hi != NULL && count < max; hi = hi->getNext()) {
  2651. #if TARGET_OS_WIN32
  2652. if (hi->moduleName) {
  2653. names[count++] = hi->moduleName;
  2654. }
  2655. #else
  2656. const char *fname = hi->fname();
  2657. if (fname) {
  2658. names[count++] = fname;
  2659. }
  2660. #endif
  2661. }
  2662. names[count] = NULL;
  2663. if (count == 0) {
  2664. // Return NULL instead of empty list if there are no images
  2665. free((void *)names);
  2666. names = NULL;
  2667. }
  2668. if (outCount) *outCount = count;
  2669. return names;
  2670. }
  2671. static const char **
  2672. _objc_copyClassNamesForImage(header_info *hi, unsigned int *outCount)
  2673. {
  2674. Module mods;
  2675. unsigned int m;
  2676. const char **list;
  2677. int count;
  2678. int allocated;
  2679. list = nil;
  2680. count = 0;
  2681. allocated = 0;
  2682. mods = hi->mod_ptr;
  2683. for (m = 0; m < hi->mod_count; m++) {
  2684. int d;
  2685. if (!mods[m].symtab) continue;
  2686. for (d = 0; d < mods[m].symtab->cls_def_cnt; d++) {
  2687. Class cls = (Class)mods[m].symtab->defs[d];
  2688. // fixme what about future-ified classes?
  2689. if (cls->isConnected()) {
  2690. if (count == allocated) {
  2691. allocated = allocated*2 + 16;
  2692. list = (const char **)
  2693. realloc((void *)list, allocated * sizeof(char *));
  2694. }
  2695. list[count++] = cls->name;
  2696. }
  2697. }
  2698. }
  2699. if (count > 0) {
  2700. // nil-terminate non-empty list
  2701. if (count == allocated) {
  2702. allocated = allocated+1;
  2703. list = (const char **)
  2704. realloc((void *)list, allocated * sizeof(char *));
  2705. }
  2706. list[count] = nil;
  2707. }
  2708. if (outCount) *outCount = count;
  2709. return list;
  2710. }
  2711. /**********************************************************************
  2712. *
  2713. **********************************************************************/
  2714. const char **
  2715. objc_copyClassNamesForImage(const char *image, unsigned int *outCount)
  2716. {
  2717. header_info *hi;
  2718. if (!image) {
  2719. if (outCount) *outCount = 0;
  2720. return NULL;
  2721. }
  2722. // Find the image.
  2723. for (hi = FirstHeader; hi != NULL; hi = hi->getNext()) {
  2724. #if TARGET_OS_WIN32
  2725. if (0 == wcscmp((TCHAR *)image, hi->moduleName)) break;
  2726. #else
  2727. if (0 == strcmp(image, hi->fname())) break;
  2728. #endif
  2729. }
  2730. if (!hi) {
  2731. if (outCount) *outCount = 0;
  2732. return NULL;
  2733. }
  2734. return _objc_copyClassNamesForImage(hi, outCount);
  2735. }
  2736. /**********************************************************************
  2737. *
  2738. **********************************************************************/
  2739. const char **
  2740. objc_copyClassNamesForImageHeader(const struct mach_header *mh, unsigned int *outCount)
  2741. {
  2742. header_info *hi;
  2743. if (!mh) {
  2744. if (outCount) *outCount = 0;
  2745. return NULL;
  2746. }
  2747. // Find the image.
  2748. for (hi = FirstHeader; hi != NULL; hi = hi->getNext()) {
  2749. if (hi->mhdr() == (const headerType *)mh) break;
  2750. }
  2751. if (!hi) {
  2752. if (outCount) *outCount = 0;
  2753. return NULL;
  2754. }
  2755. return _objc_copyClassNamesForImage(hi, outCount);
  2756. }
  2757. Class gdb_class_getClass(Class cls)
  2758. {
  2759. const char *className = cls->name;
  2760. if(!className || !strlen(className)) return Nil;
  2761. Class rCls = look_up_class(className, NO, NO);
  2762. return rCls;
  2763. }
  2764. Class gdb_object_getClass(id obj)
  2765. {
  2766. if (!obj) return nil;
  2767. return gdb_class_getClass(obj->getIsa());
  2768. }
  2769. /***********************************************************************
  2770. * objc_setMultithreaded.
  2771. **********************************************************************/
  2772. void objc_setMultithreaded (BOOL flag)
  2773. {
  2774. OBJC_WARN_DEPRECATED;
  2775. // Nothing here. Thread synchronization in the runtime is always active.
  2776. }
  2777. /***********************************************************************
  2778. * Lock management
  2779. **********************************************************************/
  2780. mutex_t selLock;
  2781. mutex_t classLock;
  2782. mutex_t methodListLock;
  2783. mutex_t cacheUpdateLock;
  2784. recursive_mutex_t loadMethodLock;
  2785. void runtime_init(void)
  2786. {
  2787. }
  2788. #endif