objc-runtime-old.mm 110 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336
  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. // Read classes from all images.
  1843. for (i = 0; i < hCount; i++) {
  1844. _objc_read_classes_from_image(hList[i]);
  1845. }
  1846. // Read categories from all images.
  1847. // But not if any other threads are running - they might
  1848. // call a category method before the fixups below are complete.
  1849. if (!_is_threaded()) {
  1850. bool needFlush = NO;
  1851. for (i = 0; i < hCount; i++) {
  1852. needFlush |= _objc_read_categories_from_image(hList[i]);
  1853. }
  1854. if (needFlush) flush_marked_caches();
  1855. categoriesLoaded = YES;
  1856. }
  1857. // Connect classes from all images.
  1858. for (i = 0; i < hCount; i++) {
  1859. _objc_connect_classes_from_image(hList[i]);
  1860. }
  1861. // Fix up class refs, selector refs, and protocol objects from all images.
  1862. for (i = 0; i < hCount; i++) {
  1863. _objc_map_class_refs_for_image(hList[i]);
  1864. _objc_fixup_selector_refs(hList[i]);
  1865. _objc_fixup_protocol_objects_for_image(hList[i]);
  1866. }
  1867. // Read categories from all images.
  1868. // But not if this is the only thread - it's more
  1869. // efficient to attach categories earlier if safe.
  1870. if (!categoriesLoaded) {
  1871. bool needFlush = NO;
  1872. for (i = 0; i < hCount; i++) {
  1873. needFlush |= _objc_read_categories_from_image(hList[i]);
  1874. }
  1875. if (needFlush) flush_marked_caches();
  1876. }
  1877. // Multi-threaded category load MUST BE LAST to avoid a race.
  1878. }
  1879. /***********************************************************************
  1880. * prepare_load_methods
  1881. * Schedule +load for classes in this image, any un-+load-ed
  1882. * superclasses in other images, and any categories in this image.
  1883. **********************************************************************/
  1884. // Recursively schedule +load for cls and any un-+load-ed superclasses.
  1885. // cls must already be connected.
  1886. static void schedule_class_load(Class cls)
  1887. {
  1888. if (cls->info & CLS_LOADED) return;
  1889. if (cls->superclass) schedule_class_load(cls->superclass);
  1890. add_class_to_loadable_list(cls);
  1891. cls->info |= CLS_LOADED;
  1892. }
  1893. void prepare_load_methods(const headerType *mhdr)
  1894. {
  1895. Module mods;
  1896. unsigned int midx;
  1897. header_info *hi;
  1898. for (hi = FirstHeader; hi; hi = hi->getNext()) {
  1899. if (mhdr == hi->mhdr()) break;
  1900. }
  1901. if (!hi) return;
  1902. if (hi->info()->isReplacement()) {
  1903. // Ignore any classes in this image
  1904. return;
  1905. }
  1906. // Major loop - process all modules in the image
  1907. mods = hi->mod_ptr;
  1908. for (midx = 0; midx < hi->mod_count; midx += 1)
  1909. {
  1910. unsigned int index;
  1911. // Skip module containing no classes
  1912. if (mods[midx].symtab == nil)
  1913. continue;
  1914. // Minor loop - process all the classes in given module
  1915. for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
  1916. {
  1917. // Locate the class description pointer
  1918. Class cls = (Class)mods[midx].symtab->defs[index];
  1919. if (cls->info & CLS_CONNECTED) {
  1920. schedule_class_load(cls);
  1921. }
  1922. }
  1923. }
  1924. // Major loop - process all modules in the header
  1925. mods = hi->mod_ptr;
  1926. // NOTE: The module and category lists are traversed backwards
  1927. // to preserve the pre-10.4 processing order. Changing the order
  1928. // would have a small chance of introducing binary compatibility bugs.
  1929. midx = (unsigned int)hi->mod_count;
  1930. while (midx-- > 0) {
  1931. unsigned int index;
  1932. unsigned int total;
  1933. Symtab symtab = mods[midx].symtab;
  1934. // Nothing to do for a module without a symbol table
  1935. if (mods[midx].symtab == nil)
  1936. continue;
  1937. // Total entries in symbol table (class entries followed
  1938. // by category entries)
  1939. total = mods[midx].symtab->cls_def_cnt +
  1940. mods[midx].symtab->cat_def_cnt;
  1941. // Minor loop - register all categories from given module
  1942. index = total;
  1943. while (index-- > mods[midx].symtab->cls_def_cnt) {
  1944. old_category *cat = (old_category *)symtab->defs[index];
  1945. add_category_to_loadable_list((Category)cat);
  1946. }
  1947. }
  1948. }
  1949. #if TARGET_OS_WIN32
  1950. void unload_class(Class cls)
  1951. {
  1952. }
  1953. #else
  1954. /***********************************************************************
  1955. * _objc_remove_classes_in_image
  1956. * Remove all classes in the given image from the runtime, because
  1957. * the image is about to be unloaded.
  1958. * Things to clean up:
  1959. * class_hash
  1960. * unconnected_class_hash
  1961. * pending subclasses list (only if class is still unconnected)
  1962. * loadable class list
  1963. * class's method caches
  1964. * class refs in all other images
  1965. **********************************************************************/
  1966. // Re-pend any class references in refs that point into [start..end)
  1967. static void rependClassReferences(Class *refs, size_t count,
  1968. uintptr_t start, uintptr_t end)
  1969. {
  1970. size_t i;
  1971. if (!refs) return;
  1972. // Process each class ref
  1973. for (i = 0; i < count; i++) {
  1974. if ((uintptr_t)(refs[i]) >= start && (uintptr_t)(refs[i]) < end) {
  1975. pendClassReference(&refs[i], refs[i]->name,
  1976. refs[i]->info & CLS_META);
  1977. refs[i] = nil;
  1978. }
  1979. }
  1980. }
  1981. void try_free(const void *p)
  1982. {
  1983. if (p && malloc_size(p)) free((void *)p);
  1984. }
  1985. // Deallocate all memory in a method list
  1986. static void unload_mlist(old_method_list *mlist)
  1987. {
  1988. int i;
  1989. for (i = 0; i < mlist->method_count; i++) {
  1990. try_free(mlist->method_list[i].method_types);
  1991. }
  1992. try_free(mlist);
  1993. }
  1994. static void unload_property_list(old_property_list *proplist)
  1995. {
  1996. uint32_t i;
  1997. if (!proplist) return;
  1998. for (i = 0; i < proplist->count; i++) {
  1999. old_property *prop = property_list_nth(proplist, i);
  2000. try_free(prop->name);
  2001. try_free(prop->attributes);
  2002. }
  2003. try_free(proplist);
  2004. }
  2005. // Deallocate all memory in a class.
  2006. void unload_class(Class cls)
  2007. {
  2008. // Free method cache
  2009. // This dereferences the cache contents; do this before freeing methods
  2010. if (cls->cache && cls->cache != &_objc_empty_cache) {
  2011. _cache_free(cls->cache);
  2012. }
  2013. // Free ivar lists
  2014. if (cls->ivars) {
  2015. int i;
  2016. for (i = 0; i < cls->ivars->ivar_count; i++) {
  2017. try_free(cls->ivars->ivar_list[i].ivar_name);
  2018. try_free(cls->ivars->ivar_list[i].ivar_type);
  2019. }
  2020. try_free(cls->ivars);
  2021. }
  2022. // Free fixed-up method lists and method list array
  2023. if (cls->methodLists) {
  2024. // more than zero method lists
  2025. if (cls->info & CLS_NO_METHOD_ARRAY) {
  2026. // one method list
  2027. unload_mlist((old_method_list *)cls->methodLists);
  2028. }
  2029. else {
  2030. // more than one method list
  2031. old_method_list **mlistp;
  2032. for (mlistp = cls->methodLists;
  2033. *mlistp != nil && *mlistp != END_OF_METHODS_LIST;
  2034. mlistp++)
  2035. {
  2036. unload_mlist(*mlistp);
  2037. }
  2038. free(cls->methodLists);
  2039. }
  2040. }
  2041. // Free protocol list
  2042. old_protocol_list *protos = cls->protocols;
  2043. while (protos) {
  2044. old_protocol_list *dead = protos;
  2045. protos = protos->next;
  2046. try_free(dead);
  2047. }
  2048. if ((cls->info & CLS_EXT)) {
  2049. if (cls->ext) {
  2050. // Free property lists and property list array
  2051. if (cls->ext->propertyLists) {
  2052. // more than zero property lists
  2053. if (cls->info & CLS_NO_PROPERTY_ARRAY) {
  2054. // one property list
  2055. old_property_list *proplist =
  2056. (old_property_list *)cls->ext->propertyLists;
  2057. unload_property_list(proplist);
  2058. } else {
  2059. // more than one property list
  2060. old_property_list **plistp;
  2061. for (plistp = cls->ext->propertyLists;
  2062. *plistp != nil;
  2063. plistp++)
  2064. {
  2065. unload_property_list(*plistp);
  2066. }
  2067. try_free(cls->ext->propertyLists);
  2068. }
  2069. }
  2070. // Free weak ivar layout
  2071. try_free(cls->ext->weak_ivar_layout);
  2072. // Free ext
  2073. try_free(cls->ext);
  2074. }
  2075. // Free non-weak ivar layout
  2076. try_free(cls->ivar_layout);
  2077. }
  2078. // Free class name
  2079. try_free(cls->name);
  2080. // Free cls
  2081. try_free(cls);
  2082. }
  2083. static void _objc_remove_classes_in_image(header_info *hi)
  2084. {
  2085. unsigned int index;
  2086. unsigned int midx;
  2087. Module mods;
  2088. mutex_locker_t lock(classLock);
  2089. // Major loop - process all modules in the image
  2090. mods = hi->mod_ptr;
  2091. for (midx = 0; midx < hi->mod_count; midx += 1)
  2092. {
  2093. // Skip module containing no classes
  2094. if (mods[midx].symtab == nil)
  2095. continue;
  2096. // Minor loop - process all the classes in given module
  2097. for (index = 0; index < mods[midx].symtab->cls_def_cnt; index += 1)
  2098. {
  2099. Class cls;
  2100. // Locate the class description pointer
  2101. cls = (Class)mods[midx].symtab->defs[index];
  2102. // Remove from loadable class list, if present
  2103. remove_class_from_loadable_list(cls);
  2104. // Remove from unconnected_class_hash and pending subclasses
  2105. if (unconnected_class_hash && NXHashMember(unconnected_class_hash, cls)) {
  2106. NXHashRemove(unconnected_class_hash, cls);
  2107. if (pendingSubclassesMap) {
  2108. // Find this class in its superclass's pending list
  2109. char *supercls_name = (char *)cls->superclass;
  2110. PendingSubclass *pending = (PendingSubclass *)
  2111. NXMapGet(pendingSubclassesMap, supercls_name);
  2112. for ( ; pending != nil; pending = pending->next) {
  2113. if (pending->subclass == cls) {
  2114. pending->subclass = Nil;
  2115. break;
  2116. }
  2117. }
  2118. }
  2119. }
  2120. // Remove from class_hash
  2121. NXHashRemove(class_hash, cls);
  2122. // Free heap memory pointed to by the class
  2123. unload_class(cls->ISA());
  2124. unload_class(cls);
  2125. }
  2126. }
  2127. // Search all other images for class refs that point back to this range.
  2128. // Un-fix and re-pend any such class refs.
  2129. // Get the location of the dying image's __OBJC segment
  2130. uintptr_t seg;
  2131. unsigned long seg_size;
  2132. seg = (uintptr_t)getsegmentdata(hi->mhdr(), "__OBJC", &seg_size);
  2133. header_info *other_hi;
  2134. for (other_hi = FirstHeader; other_hi != nil; other_hi = other_hi->getNext()) {
  2135. Class *other_refs;
  2136. size_t count;
  2137. if (other_hi == hi) continue; // skip the image being unloaded
  2138. // Fix class refs in the other image
  2139. other_refs = _getObjcClassRefs(other_hi, &count);
  2140. rependClassReferences(other_refs, count, seg, seg+seg_size);
  2141. }
  2142. }
  2143. /***********************************************************************
  2144. * _objc_remove_categories_in_image
  2145. * Remove all categories in the given image from the runtime, because
  2146. * the image is about to be unloaded.
  2147. * Things to clean up:
  2148. * unresolved category list
  2149. * loadable category list
  2150. **********************************************************************/
  2151. static void _objc_remove_categories_in_image(header_info *hi)
  2152. {
  2153. Module mods;
  2154. unsigned int midx;
  2155. // Major loop - process all modules in the header
  2156. mods = hi->mod_ptr;
  2157. for (midx = 0; midx < hi->mod_count; midx++) {
  2158. unsigned int index;
  2159. unsigned int total;
  2160. Symtab symtab = mods[midx].symtab;
  2161. // Nothing to do for a module without a symbol table
  2162. if (symtab == nil) continue;
  2163. // Total entries in symbol table (class entries followed
  2164. // by category entries)
  2165. total = symtab->cls_def_cnt + symtab->cat_def_cnt;
  2166. // Minor loop - check all categories from given module
  2167. for (index = symtab->cls_def_cnt; index < total; index++) {
  2168. old_category *cat = (old_category *)symtab->defs[index];
  2169. // Clean up loadable category list
  2170. remove_category_from_loadable_list((Category)cat);
  2171. // Clean up category_hash
  2172. if (category_hash) {
  2173. _objc_unresolved_category *cat_entry = (_objc_unresolved_category *)NXMapGet(category_hash, cat->class_name);
  2174. for ( ; cat_entry != nil; cat_entry = cat_entry->next) {
  2175. if (cat_entry->cat == cat) {
  2176. cat_entry->cat = nil;
  2177. break;
  2178. }
  2179. }
  2180. }
  2181. }
  2182. }
  2183. }
  2184. /***********************************************************************
  2185. * unload_paranoia
  2186. * Various paranoid debugging checks that look for poorly-behaving
  2187. * unloadable bundles.
  2188. * Called by _objc_unmap_image when OBJC_UNLOAD_DEBUG is set.
  2189. **********************************************************************/
  2190. static void unload_paranoia(header_info *hi)
  2191. {
  2192. // Get the location of the dying image's __OBJC segment
  2193. uintptr_t seg;
  2194. unsigned long seg_size;
  2195. seg = (uintptr_t)getsegmentdata(hi->mhdr(), "__OBJC", &seg_size);
  2196. _objc_inform("UNLOAD DEBUG: unloading image '%s' [%p..%p]",
  2197. hi->fname(), (void *)seg, (void*)(seg+seg_size));
  2198. mutex_locker_t lock(classLock);
  2199. // Make sure the image contains no categories on surviving classes.
  2200. {
  2201. Module mods;
  2202. unsigned int midx;
  2203. // Major loop - process all modules in the header
  2204. mods = hi->mod_ptr;
  2205. for (midx = 0; midx < hi->mod_count; midx++) {
  2206. unsigned int index;
  2207. unsigned int total;
  2208. Symtab symtab = mods[midx].symtab;
  2209. // Nothing to do for a module without a symbol table
  2210. if (symtab == nil) continue;
  2211. // Total entries in symbol table (class entries followed
  2212. // by category entries)
  2213. total = symtab->cls_def_cnt + symtab->cat_def_cnt;
  2214. // Minor loop - check all categories from given module
  2215. for (index = symtab->cls_def_cnt; index < total; index++) {
  2216. old_category *cat = (old_category *)symtab->defs[index];
  2217. struct objc_class query;
  2218. query.name = cat->class_name;
  2219. if (NXHashMember(class_hash, &query)) {
  2220. _objc_inform("UNLOAD DEBUG: dying image contains category '%s(%s)' on surviving class '%s'!", cat->class_name, cat->category_name, cat->class_name);
  2221. }
  2222. }
  2223. }
  2224. }
  2225. // Make sure no surviving class is in the dying image.
  2226. // Make sure no surviving class has a superclass in the dying image.
  2227. // fixme check method implementations too
  2228. {
  2229. Class cls;
  2230. NXHashState state;
  2231. state = NXInitHashState(class_hash);
  2232. while (NXNextHashState(class_hash, &state, (void **)&cls)) {
  2233. if ((vm_address_t)cls >= seg &&
  2234. (vm_address_t)cls < seg+seg_size)
  2235. {
  2236. _objc_inform("UNLOAD DEBUG: dying image contains surviving class '%s'!", cls->name);
  2237. }
  2238. if ((vm_address_t)cls->superclass >= seg &&
  2239. (vm_address_t)cls->superclass < seg+seg_size)
  2240. {
  2241. _objc_inform("UNLOAD DEBUG: dying image contains superclass '%s' of surviving class '%s'!", cls->superclass->name, cls->name);
  2242. }
  2243. }
  2244. }
  2245. }
  2246. /***********************************************************************
  2247. * _unload_image
  2248. * Only handles MH_BUNDLE for now.
  2249. * Locking: loadMethodLock acquired by unmap_image
  2250. **********************************************************************/
  2251. void _unload_image(header_info *hi)
  2252. {
  2253. loadMethodLock.assertLocked();
  2254. // Cleanup:
  2255. // Remove image's classes from the class list and free auxiliary data.
  2256. // Remove image's unresolved or loadable categories and free auxiliary data
  2257. // Remove image's unresolved class refs.
  2258. _objc_remove_classes_in_image(hi);
  2259. _objc_remove_categories_in_image(hi);
  2260. _objc_remove_pending_class_refs_in_image(hi);
  2261. if (hi->proto_refs) try_free(hi->proto_refs);
  2262. // Perform various debugging checks if requested.
  2263. if (DebugUnload) unload_paranoia(hi);
  2264. }
  2265. #endif
  2266. /***********************************************************************
  2267. * objc_addClass. Add the specified class to the table of known classes,
  2268. * after doing a little verification and fixup.
  2269. **********************************************************************/
  2270. void objc_addClass (Class cls)
  2271. {
  2272. OBJC_WARN_DEPRECATED;
  2273. // Synchronize access to hash table
  2274. mutex_locker_t lock(classLock);
  2275. // Make sure both the class and the metaclass have caches!
  2276. // Clear all bits of the info fields except CLS_CLASS and CLS_META.
  2277. // Normally these bits are already clear but if someone tries to cons
  2278. // up their own class on the fly they might need to be cleared.
  2279. if (cls->cache == nil) {
  2280. cls->cache = (Cache) &_objc_empty_cache;
  2281. cls->info = CLS_CLASS;
  2282. }
  2283. if (cls->ISA()->cache == nil) {
  2284. cls->ISA()->cache = (Cache) &_objc_empty_cache;
  2285. cls->ISA()->info = CLS_META;
  2286. }
  2287. // methodLists should be:
  2288. // 1. nil (Tiger and later only)
  2289. // 2. A -1 terminated method list array
  2290. // In either case, CLS_NO_METHOD_ARRAY remains clear.
  2291. // If the user manipulates the method list directly,
  2292. // they must use the magic private format.
  2293. // Add the class to the table
  2294. (void) NXHashInsert (class_hash, cls);
  2295. // Superclass is no longer a leaf for cache flushing
  2296. if (cls->superclass && (cls->superclass->info & CLS_LEAF)) {
  2297. cls->superclass->clearInfo(CLS_LEAF);
  2298. cls->superclass->ISA()->clearInfo(CLS_LEAF);
  2299. }
  2300. }
  2301. /***********************************************************************
  2302. * _objcTweakMethodListPointerForClass.
  2303. * Change the class's method list pointer to a method list array.
  2304. * Does nothing if the method list pointer is already a method list array.
  2305. * If the class is currently in use, methodListLock must be held by the caller.
  2306. **********************************************************************/
  2307. static void _objcTweakMethodListPointerForClass(Class cls)
  2308. {
  2309. old_method_list * originalList;
  2310. const int initialEntries = 4;
  2311. size_t mallocSize;
  2312. old_method_list ** ptr;
  2313. // Do nothing if methodLists is already an array.
  2314. if (cls->methodLists && !(cls->info & CLS_NO_METHOD_ARRAY)) return;
  2315. // Remember existing list
  2316. originalList = (old_method_list *) cls->methodLists;
  2317. // Allocate and zero a method list array
  2318. mallocSize = sizeof(old_method_list *) * initialEntries;
  2319. ptr = (old_method_list **) calloc(1, mallocSize);
  2320. // Insert the existing list into the array
  2321. ptr[initialEntries - 1] = END_OF_METHODS_LIST;
  2322. ptr[0] = originalList;
  2323. // Replace existing list with array
  2324. cls->methodLists = ptr;
  2325. cls->clearInfo(CLS_NO_METHOD_ARRAY);
  2326. }
  2327. /***********************************************************************
  2328. * _objc_insertMethods.
  2329. * Adds methods to a class.
  2330. * Does not flush any method caches.
  2331. * Does not take any locks.
  2332. * If the class is already in use, use class_addMethods() instead.
  2333. **********************************************************************/
  2334. void _objc_insertMethods(Class cls, old_method_list *mlist, old_category *cat)
  2335. {
  2336. old_method_list ***list;
  2337. old_method_list **ptr;
  2338. ptrdiff_t endIndex;
  2339. size_t oldSize;
  2340. size_t newSize;
  2341. if (!cls->methodLists) {
  2342. // cls has no methods - simply use this method list
  2343. cls->methodLists = (old_method_list **)mlist;
  2344. cls->setInfo(CLS_NO_METHOD_ARRAY);
  2345. return;
  2346. }
  2347. // Log any existing methods being replaced
  2348. if (PrintReplacedMethods) {
  2349. int i;
  2350. for (i = 0; i < mlist->method_count; i++) {
  2351. extern IMP findIMPInClass(Class cls, SEL sel);
  2352. SEL sel = sel_registerName((char *)mlist->method_list[i].method_name);
  2353. IMP newImp = mlist->method_list[i].method_imp;
  2354. IMP oldImp;
  2355. if ((oldImp = findIMPInClass(cls, sel))) {
  2356. logReplacedMethod(cls->name, sel, ISMETA(cls),
  2357. cat ? cat->category_name : nil,
  2358. oldImp, newImp);
  2359. }
  2360. }
  2361. }
  2362. // Create method list array if necessary
  2363. _objcTweakMethodListPointerForClass(cls);
  2364. list = &cls->methodLists;
  2365. // Locate unused entry for insertion point
  2366. ptr = *list;
  2367. while ((*ptr != 0) && (*ptr != END_OF_METHODS_LIST))
  2368. ptr += 1;
  2369. // If array is full, add to it
  2370. if (*ptr == END_OF_METHODS_LIST)
  2371. {
  2372. // Calculate old and new dimensions
  2373. endIndex = ptr - *list;
  2374. oldSize = (endIndex + 1) * sizeof(void *);
  2375. newSize = oldSize + sizeof(old_method_list *); // only increase by 1
  2376. // Grow the method list array by one.
  2377. *list = (old_method_list **)realloc(*list, newSize);
  2378. // Zero out addition part of new array
  2379. bzero (&((*list)[endIndex]), newSize - oldSize);
  2380. // Place new end marker
  2381. (*list)[(newSize/sizeof(void *)) - 1] = END_OF_METHODS_LIST;
  2382. // Insertion point corresponds to old array end
  2383. ptr = &((*list)[endIndex]);
  2384. }
  2385. // Right shift existing entries by one
  2386. bcopy (*list, (*list) + 1, (uint8_t *)ptr - (uint8_t *)*list);
  2387. // Insert at method list at beginning of array
  2388. **list = mlist;
  2389. }
  2390. /***********************************************************************
  2391. * _objc_removeMethods.
  2392. * Remove methods from a class.
  2393. * Does not take any locks.
  2394. * Does not flush any method caches.
  2395. * If the class is currently in use, use class_removeMethods() instead.
  2396. **********************************************************************/
  2397. void _objc_removeMethods(Class cls, old_method_list *mlist)
  2398. {
  2399. old_method_list ***list;
  2400. old_method_list **ptr;
  2401. if (cls->methodLists == nil) {
  2402. // cls has no methods
  2403. return;
  2404. }
  2405. if (cls->methodLists == (old_method_list **)mlist) {
  2406. // mlist is the class's only method list - erase it
  2407. cls->methodLists = nil;
  2408. return;
  2409. }
  2410. if (cls->info & CLS_NO_METHOD_ARRAY) {
  2411. // cls has only one method list, and this isn't it - do nothing
  2412. return;
  2413. }
  2414. // cls has a method list array - search it
  2415. list = &cls->methodLists;
  2416. // Locate list in the array
  2417. ptr = *list;
  2418. while (*ptr != mlist) {
  2419. // fix for radar # 2538790
  2420. if ( *ptr == END_OF_METHODS_LIST ) return;
  2421. ptr += 1;
  2422. }
  2423. // Remove this entry
  2424. *ptr = 0;
  2425. // Left shift the following entries
  2426. while (*(++ptr) != END_OF_METHODS_LIST)
  2427. *(ptr-1) = *ptr;
  2428. *(ptr-1) = 0;
  2429. }
  2430. /***********************************************************************
  2431. * _objc_add_category. Install the specified category's methods and
  2432. * protocols into the class it augments.
  2433. * The class is assumed not to be in use yet: no locks are taken and
  2434. * no method caches are flushed.
  2435. **********************************************************************/
  2436. static inline void _objc_add_category(Class cls, old_category *category, int version)
  2437. {
  2438. if (PrintConnecting) {
  2439. _objc_inform("CONNECT: attaching category '%s (%s)'", cls->name, category->category_name);
  2440. }
  2441. // Augment instance methods
  2442. if (category->instance_methods)
  2443. _objc_insertMethods (cls, category->instance_methods, category);
  2444. // Augment class methods
  2445. if (category->class_methods)
  2446. _objc_insertMethods (cls->ISA(), category->class_methods, category);
  2447. // Augment protocols
  2448. if ((version >= 5) && category->protocols)
  2449. {
  2450. if (cls->ISA()->version >= 5)
  2451. {
  2452. category->protocols->next = cls->protocols;
  2453. cls->protocols = category->protocols;
  2454. cls->ISA()->protocols = category->protocols;
  2455. }
  2456. else
  2457. {
  2458. _objc_inform ("unable to add protocols from category %s...\n", category->category_name);
  2459. _objc_inform ("class `%s' must be recompiled\n", category->class_name);
  2460. }
  2461. }
  2462. // Augment instance properties
  2463. if (version >= 7 && category->instance_properties) {
  2464. if (cls->ISA()->version >= 6) {
  2465. _class_addProperties(cls, category->instance_properties);
  2466. } else {
  2467. _objc_inform ("unable to add instance properties from category %s...\n", category->category_name);
  2468. _objc_inform ("class `%s' must be recompiled\n", category->class_name);
  2469. }
  2470. }
  2471. // Augment class properties
  2472. if (version >= 7 && category->hasClassPropertiesField() &&
  2473. category->class_properties)
  2474. {
  2475. if (cls->ISA()->version >= 6) {
  2476. _class_addProperties(cls->ISA(), category->class_properties);
  2477. } else {
  2478. _objc_inform ("unable to add class properties from category %s...\n", category->category_name);
  2479. _objc_inform ("class `%s' must be recompiled\n", category->class_name);
  2480. }
  2481. }
  2482. }
  2483. /***********************************************************************
  2484. * _objc_add_category_flush_caches. Install the specified category's
  2485. * methods into the class it augments, and flush the class' method cache.
  2486. * Return YES if some method caches now need to be flushed.
  2487. **********************************************************************/
  2488. static bool _objc_add_category_flush_caches(Class cls, old_category *category, int version)
  2489. {
  2490. bool needFlush = NO;
  2491. // Install the category's methods into its intended class
  2492. {
  2493. mutex_locker_t lock(methodListLock);
  2494. _objc_add_category (cls, category, version);
  2495. }
  2496. // Queue for cache flushing so category's methods can get called
  2497. if (category->instance_methods) {
  2498. cls->setInfo(CLS_FLUSH_CACHE);
  2499. needFlush = YES;
  2500. }
  2501. if (category->class_methods) {
  2502. cls->ISA()->setInfo(CLS_FLUSH_CACHE);
  2503. needFlush = YES;
  2504. }
  2505. return needFlush;
  2506. }
  2507. /***********************************************************************
  2508. * reverse_cat
  2509. * Reverse the given linked list of pending categories.
  2510. * The pending category list is built backwards, and needs to be
  2511. * reversed before actually attaching the categories to a class.
  2512. * Returns the head of the new linked list.
  2513. **********************************************************************/
  2514. static _objc_unresolved_category *reverse_cat(_objc_unresolved_category *cat)
  2515. {
  2516. _objc_unresolved_category *prev;
  2517. _objc_unresolved_category *cur;
  2518. _objc_unresolved_category *ahead;
  2519. if (!cat) return nil;
  2520. prev = nil;
  2521. cur = cat;
  2522. ahead = cat->next;
  2523. while (cur) {
  2524. ahead = cur->next;
  2525. cur->next = prev;
  2526. prev = cur;
  2527. cur = ahead;
  2528. }
  2529. return prev;
  2530. }
  2531. /***********************************************************************
  2532. * resolve_categories_for_class.
  2533. * Install all existing categories intended for the specified class.
  2534. * cls must be a true class and not a metaclass.
  2535. **********************************************************************/
  2536. static void resolve_categories_for_class(Class cls)
  2537. {
  2538. _objc_unresolved_category * pending;
  2539. _objc_unresolved_category * next;
  2540. // Nothing to do if there are no categories at all
  2541. if (!category_hash) return;
  2542. // Locate and remove first element in category list
  2543. // associated with this class
  2544. pending = (_objc_unresolved_category *)
  2545. NXMapKeyFreeingRemove (category_hash, cls->name);
  2546. // Traverse the list of categories, if any, registered for this class
  2547. // The pending list is built backwards. Reverse it and walk forwards.
  2548. pending = reverse_cat(pending);
  2549. while (pending) {
  2550. if (pending->cat) {
  2551. // Install the category
  2552. // use the non-flush-cache version since we are only
  2553. // called from the class intialization code
  2554. _objc_add_category(cls, pending->cat, (int)pending->version);
  2555. }
  2556. // Delink and reclaim this registration
  2557. next = pending->next;
  2558. free(pending);
  2559. pending = next;
  2560. }
  2561. }
  2562. /***********************************************************************
  2563. * _objc_resolve_categories_for_class.
  2564. * Public version of resolve_categories_for_class. This was
  2565. * exported pre-10.4 for Omni et al. to workaround a problem
  2566. * with too-lazy category attachment.
  2567. * cls should be a class, but this function can also cope with metaclasses.
  2568. **********************************************************************/
  2569. void _objc_resolve_categories_for_class(Class cls)
  2570. {
  2571. // If cls is a metaclass, get the class.
  2572. // resolve_categories_for_class() requires a real class to work correctly.
  2573. if (ISMETA(cls)) {
  2574. if (strncmp(cls->name, "_%", 2) == 0) {
  2575. // Posee's meta's name is smashed and isn't in the class_hash,
  2576. // so objc_getClass doesn't work.
  2577. const char *baseName = strchr(cls->name, '%'); // get posee's real name
  2578. cls = objc_getClass(baseName);
  2579. } else {
  2580. cls = objc_getClass(cls->name);
  2581. }
  2582. }
  2583. resolve_categories_for_class(cls);
  2584. }
  2585. /***********************************************************************
  2586. * _objc_register_category.
  2587. * Process a category read from an image.
  2588. * If the category's class exists, attach the category immediately.
  2589. * Classes that need cache flushing are marked but not flushed.
  2590. * If the category's class does not exist yet, pend the category for
  2591. * later attachment. Pending categories are attached in the order
  2592. * they were discovered.
  2593. * Returns YES if some method caches now need to be flushed.
  2594. **********************************************************************/
  2595. static bool _objc_register_category(old_category *cat, int version)
  2596. {
  2597. _objc_unresolved_category * new_cat;
  2598. _objc_unresolved_category * old;
  2599. Class theClass;
  2600. // If the category's class exists, attach the category.
  2601. if ((theClass = objc_lookUpClass(cat->class_name))) {
  2602. return _objc_add_category_flush_caches(theClass, cat, version);
  2603. }
  2604. // If the category's class exists but is unconnected,
  2605. // then attach the category to the class but don't bother
  2606. // flushing any method caches (because they must be empty).
  2607. // YES unconnected, NO class_handler
  2608. if ((theClass = look_up_class(cat->class_name, YES, NO))) {
  2609. _objc_add_category(theClass, cat, version);
  2610. return NO;
  2611. }
  2612. // Category's class does not exist yet.
  2613. // Save the category for later attachment.
  2614. if (PrintConnecting) {
  2615. _objc_inform("CONNECT: pending category '%s (%s)'", cat->class_name, cat->category_name);
  2616. }
  2617. // Create category lookup table if needed
  2618. if (!category_hash)
  2619. category_hash = NXCreateMapTable(NXStrValueMapPrototype, 128);
  2620. // Locate an existing list of categories, if any, for the class.
  2621. old = (_objc_unresolved_category *)
  2622. NXMapGet (category_hash, cat->class_name);
  2623. // Register the category to be fixed up later.
  2624. // The category list is built backwards, and is reversed again
  2625. // by resolve_categories_for_class().
  2626. new_cat = (_objc_unresolved_category *)
  2627. malloc(sizeof(_objc_unresolved_category));
  2628. new_cat->next = old;
  2629. new_cat->cat = cat;
  2630. new_cat->version = version;
  2631. (void) NXMapKeyCopyingInsert (category_hash, cat->class_name, new_cat);
  2632. return NO;
  2633. }
  2634. const char **objc_copyImageNames(unsigned int *outCount)
  2635. {
  2636. header_info *hi;
  2637. int count = 0;
  2638. int max = HeaderCount;
  2639. #if TARGET_OS_WIN32
  2640. const TCHAR **names = (const TCHAR **)calloc(max+1, sizeof(TCHAR *));
  2641. #else
  2642. const char **names = (const char **)calloc(max+1, sizeof(char *));
  2643. #endif
  2644. for (hi = FirstHeader; hi != NULL && count < max; hi = hi->getNext()) {
  2645. #if TARGET_OS_WIN32
  2646. if (hi->moduleName) {
  2647. names[count++] = hi->moduleName;
  2648. }
  2649. #else
  2650. const char *fname = hi->fname();
  2651. if (fname) {
  2652. names[count++] = fname;
  2653. }
  2654. #endif
  2655. }
  2656. names[count] = NULL;
  2657. if (count == 0) {
  2658. // Return NULL instead of empty list if there are no images
  2659. free((void *)names);
  2660. names = NULL;
  2661. }
  2662. if (outCount) *outCount = count;
  2663. return names;
  2664. }
  2665. static const char **
  2666. _objc_copyClassNamesForImage(header_info *hi, unsigned int *outCount)
  2667. {
  2668. Module mods;
  2669. unsigned int m;
  2670. const char **list;
  2671. int count;
  2672. int allocated;
  2673. list = nil;
  2674. count = 0;
  2675. allocated = 0;
  2676. mods = hi->mod_ptr;
  2677. for (m = 0; m < hi->mod_count; m++) {
  2678. int d;
  2679. if (!mods[m].symtab) continue;
  2680. for (d = 0; d < mods[m].symtab->cls_def_cnt; d++) {
  2681. Class cls = (Class)mods[m].symtab->defs[d];
  2682. // fixme what about future-ified classes?
  2683. if (cls->isConnected()) {
  2684. if (count == allocated) {
  2685. allocated = allocated*2 + 16;
  2686. list = (const char **)
  2687. realloc((void *)list, allocated * sizeof(char *));
  2688. }
  2689. list[count++] = cls->name;
  2690. }
  2691. }
  2692. }
  2693. if (count > 0) {
  2694. // nil-terminate non-empty list
  2695. if (count == allocated) {
  2696. allocated = allocated+1;
  2697. list = (const char **)
  2698. realloc((void *)list, allocated * sizeof(char *));
  2699. }
  2700. list[count] = nil;
  2701. }
  2702. if (outCount) *outCount = count;
  2703. return list;
  2704. }
  2705. /**********************************************************************
  2706. *
  2707. **********************************************************************/
  2708. const char **
  2709. objc_copyClassNamesForImage(const char *image, unsigned int *outCount)
  2710. {
  2711. header_info *hi;
  2712. if (!image) {
  2713. if (outCount) *outCount = 0;
  2714. return NULL;
  2715. }
  2716. // Find the image.
  2717. for (hi = FirstHeader; hi != NULL; hi = hi->getNext()) {
  2718. #if TARGET_OS_WIN32
  2719. if (0 == wcscmp((TCHAR *)image, hi->moduleName)) break;
  2720. #else
  2721. if (0 == strcmp(image, hi->fname())) break;
  2722. #endif
  2723. }
  2724. if (!hi) {
  2725. if (outCount) *outCount = 0;
  2726. return NULL;
  2727. }
  2728. return _objc_copyClassNamesForImage(hi, outCount);
  2729. }
  2730. /**********************************************************************
  2731. *
  2732. **********************************************************************/
  2733. const char **
  2734. objc_copyClassNamesForImageHeader(const struct mach_header *mh, unsigned int *outCount)
  2735. {
  2736. header_info *hi;
  2737. if (!mh) {
  2738. if (outCount) *outCount = 0;
  2739. return NULL;
  2740. }
  2741. // Find the image.
  2742. for (hi = FirstHeader; hi != NULL; hi = hi->getNext()) {
  2743. if (hi->mhdr() == (const headerType *)mh) break;
  2744. }
  2745. if (!hi) {
  2746. if (outCount) *outCount = 0;
  2747. return NULL;
  2748. }
  2749. return _objc_copyClassNamesForImage(hi, outCount);
  2750. }
  2751. Class gdb_class_getClass(Class cls)
  2752. {
  2753. const char *className = cls->name;
  2754. if(!className || !strlen(className)) return Nil;
  2755. Class rCls = look_up_class(className, NO, NO);
  2756. return rCls;
  2757. }
  2758. Class gdb_object_getClass(id obj)
  2759. {
  2760. if (!obj) return nil;
  2761. return gdb_class_getClass(obj->getIsa());
  2762. }
  2763. /***********************************************************************
  2764. * objc_setMultithreaded.
  2765. **********************************************************************/
  2766. void objc_setMultithreaded (BOOL flag)
  2767. {
  2768. OBJC_WARN_DEPRECATED;
  2769. // Nothing here. Thread synchronization in the runtime is always active.
  2770. }
  2771. /***********************************************************************
  2772. * Lock management
  2773. **********************************************************************/
  2774. mutex_t selLock;
  2775. mutex_t classLock;
  2776. mutex_t methodListLock;
  2777. mutex_t cacheUpdateLock;
  2778. recursive_mutex_t loadMethodLock;
  2779. void lock_init(void)
  2780. {
  2781. }
  2782. #endif