appdomain.c 107 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603
  1. /**
  2. * \file
  3. * AppDomain functions
  4. *
  5. * Authors:
  6. * Dietmar Maurer (dietmar@ximian.com)
  7. * Patrik Torstensson
  8. * Gonzalo Paniagua Javier (gonzalo@ximian.com)
  9. *
  10. * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  11. * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  12. * Copyright 2012 Xamarin Inc
  13. * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  14. */
  15. #include <config.h>
  16. #include <glib.h>
  17. #include <string.h>
  18. #include <errno.h>
  19. #include <time.h>
  20. #include <sys/types.h>
  21. #include <sys/stat.h>
  22. #ifdef HAVE_SYS_TIME_H
  23. #include <sys/time.h>
  24. #endif
  25. #ifdef HAVE_UNISTD_H
  26. #include <unistd.h>
  27. #endif
  28. #ifdef HAVE_UTIME_H
  29. #include <utime.h>
  30. #else
  31. #ifdef HAVE_SYS_UTIME_H
  32. #include <sys/utime.h>
  33. #endif
  34. #endif
  35. #include <mono/metadata/gc-internals.h>
  36. #include <mono/metadata/object.h>
  37. #include <mono/metadata/appdomain-icalls.h>
  38. #include <mono/metadata/class-init.h>
  39. #include <mono/metadata/domain-internals.h>
  40. #include "mono/metadata/metadata-internals.h"
  41. #include <mono/metadata/assembly-internals.h>
  42. #include <mono/metadata/exception.h>
  43. #include <mono/metadata/exception-internals.h>
  44. #include <mono/metadata/threads.h>
  45. #include <mono/metadata/threadpool.h>
  46. #include <mono/metadata/tabledefs.h>
  47. #include <mono/metadata/mono-gc.h>
  48. #include <mono/metadata/mono-hash-internals.h>
  49. #include <mono/metadata/marshal.h>
  50. #include <mono/metadata/marshal-internals.h>
  51. #include <mono/metadata/monitor.h>
  52. #include <mono/metadata/mono-debug.h>
  53. #include <mono/metadata/attach.h>
  54. #include <mono/metadata/w32file.h>
  55. #include <mono/metadata/lock-tracer.h>
  56. #include <mono/metadata/console-io.h>
  57. #include <mono/metadata/threads-types.h>
  58. #include <mono/metadata/tokentype.h>
  59. #include <mono/metadata/profiler-private.h>
  60. #include <mono/metadata/reflection-internals.h>
  61. #include <mono/metadata/abi-details.h>
  62. #include <mono/metadata/w32socket.h>
  63. #include <mono/utils/mono-uri.h>
  64. #include <mono/utils/mono-logger-internals.h>
  65. #include <mono/utils/mono-path.h>
  66. #include <mono/utils/mono-stdlib.h>
  67. #include <mono/utils/mono-io-portability.h>
  68. #include <mono/utils/mono-error-internals.h>
  69. #include <mono/utils/atomic.h>
  70. #include <mono/utils/mono-memory-model.h>
  71. #include <mono/utils/mono-threads.h>
  72. #include <mono/metadata/w32handle.h>
  73. #include <mono/metadata/w32error.h>
  74. #include <mono/utils/w32api.h>
  75. #ifdef ENABLE_PERFTRACING
  76. #include <eventpipe/ds-server.h>
  77. #endif
  78. #ifdef HOST_WIN32
  79. #include <direct.h>
  80. #endif
  81. #include "object-internals.h"
  82. #include "icall-decl.h"
  83. typedef struct
  84. {
  85. int runtime_count;
  86. int assemblybinding_count;
  87. MonoDomain *domain;
  88. gchar *filename;
  89. } RuntimeConfig;
  90. #ifndef ENABLE_NETCORE
  91. static gunichar2 process_guid [36];
  92. static gboolean process_guid_set = FALSE;
  93. #endif
  94. static gboolean no_exec = FALSE;
  95. #ifdef ENABLE_NETCORE
  96. static int n_appctx_props;
  97. static gunichar2 **appctx_keys;
  98. static gunichar2 **appctx_values;
  99. #endif
  100. static const char *
  101. mono_check_corlib_version_internal (void);
  102. static MonoAssembly *
  103. mono_domain_assembly_preload (MonoAssemblyLoadContext *alc,
  104. MonoAssemblyName *aname,
  105. gchar **assemblies_path,
  106. gboolean refonly,
  107. gpointer user_data,
  108. MonoError *error);
  109. static MonoAssembly *
  110. mono_domain_assembly_search (MonoAssemblyLoadContext *alc, MonoAssembly *requesting,
  111. MonoAssemblyName *aname,
  112. gboolean refonly,
  113. gboolean postload,
  114. gpointer user_data,
  115. MonoError *error);
  116. static gboolean ignore_version_and_key_when_finding_assemblies_already_loaded = FALSE;
  117. void
  118. mono_set_ignore_version_and_key_when_finding_assemblies_already_loaded(gboolean value)
  119. {
  120. ignore_version_and_key_when_finding_assemblies_already_loaded = value;
  121. }
  122. static void
  123. mono_domain_fire_assembly_load (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer user_data, MonoError *error_out);
  124. static gboolean
  125. mono_domain_asmctx_from_path (const char *fname, MonoAssembly *requesting_assembly, gpointer user_data, MonoAssemblyContextKind *out_asmctx);
  126. static void
  127. add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *ht);
  128. #if ENABLE_NETCORE
  129. static void
  130. add_assembly_to_alc (MonoAssemblyLoadContext *alc, MonoAssembly *ass);
  131. #endif
  132. #ifndef ENABLE_NETCORE
  133. static MonoAppDomainHandle
  134. mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetupHandle setup, MonoError *error);
  135. static MonoDomain *
  136. mono_domain_create_appdomain_checked (char *friendly_name, char *configuration_file, MonoError *error);
  137. #endif
  138. static void
  139. mono_context_set_default_context (MonoDomain *domain);
  140. static char *
  141. get_shadow_assembly_location_base (MonoDomain *domain, MonoError *error);
  142. static MonoLoadFunc load_function = NULL;
  143. /* Lazy class loading functions */
  144. static GENERATE_GET_CLASS_WITH_CACHE (assembly, "System.Reflection", "Assembly");
  145. #ifdef ENABLE_NETCORE
  146. static GENERATE_GET_CLASS_WITH_CACHE (app_context, "System", "AppContext");
  147. #endif
  148. #ifndef ENABLE_NETCORE
  149. GENERATE_GET_CLASS_WITH_CACHE (appdomain, MONO_APPDOMAIN_CLASS_NAME_SPACE, MONO_APPDOMAIN_CLASS_NAME);
  150. GENERATE_GET_CLASS_WITH_CACHE (appdomain_setup, MONO_APPDOMAIN_SETUP_CLASS_NAME_SPACE, MONO_APPDOMAIN_SETUP_CLASS_NAME);
  151. #else
  152. MonoClass*
  153. mono_class_get_appdomain_class (void)
  154. {
  155. return mono_defaults.object_class;
  156. }
  157. #endif
  158. static MonoDomain *
  159. mono_domain_from_appdomain_handle (MonoAppDomainHandle appdomain);
  160. static void
  161. mono_error_set_appdomain_unloaded (MonoError *error)
  162. {
  163. mono_error_set_generic_error (error, "System", "AppDomainUnloadedException", "");
  164. }
  165. void
  166. mono_install_runtime_load (MonoLoadFunc func)
  167. {
  168. load_function = func;
  169. }
  170. MonoDomain*
  171. mono_runtime_load (const char *filename, const char *runtime_version)
  172. {
  173. g_assert (load_function);
  174. return load_function (filename, runtime_version);
  175. }
  176. /**
  177. * mono_runtime_set_no_exec:
  178. *
  179. * Instructs the runtime to operate in static mode, i.e. avoid/do not
  180. * allow managed code execution. This is useful for running the AOT
  181. * compiler on platforms which allow full-aot execution only. This
  182. * should be called before mono_runtime_init ().
  183. */
  184. void
  185. mono_runtime_set_no_exec (gboolean val)
  186. {
  187. no_exec = val;
  188. }
  189. /**
  190. * mono_runtime_get_no_exec:
  191. *
  192. * If true, then the runtime will not allow managed code execution.
  193. */
  194. gboolean
  195. mono_runtime_get_no_exec (void)
  196. {
  197. return no_exec;
  198. }
  199. static void
  200. create_domain_objects (MonoDomain *domain)
  201. {
  202. HANDLE_FUNCTION_ENTER ();
  203. ERROR_DECL (error);
  204. MonoDomain *old_domain = mono_domain_get ();
  205. MonoStringHandle arg;
  206. MonoVTable *string_vt;
  207. MonoClassField *string_empty_fld;
  208. if (domain != old_domain) {
  209. mono_thread_push_appdomain_ref (domain);
  210. mono_domain_set_internal_with_options (domain, FALSE);
  211. }
  212. /*
  213. * Initialize String.Empty. This enables the removal of
  214. * the static cctor of the String class.
  215. */
  216. string_vt = mono_class_vtable_checked (domain, mono_defaults.string_class, error);
  217. mono_error_assert_ok (error);
  218. string_empty_fld = mono_class_get_field_from_name_full (mono_defaults.string_class, "Empty", NULL);
  219. g_assert (string_empty_fld);
  220. MonoStringHandle empty_str = mono_string_new_handle (domain, "", error);
  221. mono_error_assert_ok (error);
  222. empty_str = mono_string_intern_checked (empty_str, error);
  223. mono_error_assert_ok (error);
  224. mono_field_static_set_value_internal (string_vt, string_empty_fld, MONO_HANDLE_RAW (empty_str));
  225. domain->empty_string = MONO_HANDLE_RAW (empty_str);
  226. mono_gc_wbarrier_generic_nostore_internal (&domain->empty_string);
  227. /*
  228. * Create an instance early since we can't do it when there is no memory.
  229. */
  230. arg = mono_string_new_handle (domain, "Out of memory", error);
  231. mono_error_assert_ok (error);
  232. domain->out_of_memory_ex = MONO_HANDLE_RAW (mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "OutOfMemoryException", arg, NULL_HANDLE_STRING, error));
  233. mono_gc_wbarrier_generic_nostore_internal (&domain->out_of_memory_ex);
  234. mono_error_assert_ok (error);
  235. /*
  236. * These two are needed because the signal handlers might be executing on
  237. * an alternate stack, and Boehm GC can't handle that.
  238. */
  239. arg = mono_string_new_handle (domain, "A null value was found where an object instance was required", error);
  240. mono_error_assert_ok (error);
  241. domain->null_reference_ex = MONO_HANDLE_RAW (mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "NullReferenceException", arg, NULL_HANDLE_STRING, error));
  242. mono_gc_wbarrier_generic_nostore_internal (&domain->null_reference_ex);
  243. mono_error_assert_ok (error);
  244. arg = mono_string_new_handle (domain, "The requested operation caused a stack overflow.", error);
  245. mono_error_assert_ok (error);
  246. domain->stack_overflow_ex = MONO_HANDLE_RAW (mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "StackOverflowException", arg, NULL_HANDLE_STRING, error));
  247. mono_gc_wbarrier_generic_nostore_internal (&domain->stack_overflow_ex);
  248. mono_error_assert_ok (error);
  249. /*The ephemeron tombstone i*/
  250. domain->ephemeron_tombstone = MONO_HANDLE_RAW (mono_object_new_handle (domain, mono_defaults.object_class, error));
  251. mono_gc_wbarrier_generic_nostore_internal (&domain->ephemeron_tombstone);
  252. mono_error_assert_ok (error);
  253. if (domain != old_domain) {
  254. mono_thread_pop_appdomain_ref ();
  255. mono_domain_set_internal_with_options (old_domain, FALSE);
  256. }
  257. /*
  258. * This class is used during exception handling, so initialize it here, to prevent
  259. * stack overflows while handling stack overflows.
  260. */
  261. mono_class_init_internal (mono_class_create_array (mono_defaults.int_class, 1));
  262. HANDLE_FUNCTION_RETURN ();
  263. }
  264. /**
  265. * mono_runtime_init:
  266. * \param domain domain returned by \c mono_init
  267. *
  268. * Initialize the core AppDomain: this function will run also some
  269. * IL initialization code, so it needs the execution engine to be fully
  270. * operational.
  271. *
  272. * \c AppDomain.SetupInformation is set up in \c mono_runtime_exec_main, where
  273. * we know the \c entry_assembly.
  274. *
  275. */
  276. void
  277. mono_runtime_init (MonoDomain *domain, MonoThreadStartCB start_cb, MonoThreadAttachCB attach_cb)
  278. {
  279. ERROR_DECL (error);
  280. mono_runtime_init_checked (domain, start_cb, attach_cb, error);
  281. mono_error_cleanup (error);
  282. }
  283. void
  284. mono_runtime_init_checked (MonoDomain *domain, MonoThreadStartCB start_cb, MonoThreadAttachCB attach_cb, MonoError *error)
  285. {
  286. HANDLE_FUNCTION_ENTER ();
  287. MonoAppDomainHandle ad;
  288. error_init (error);
  289. mono_portability_helpers_init ();
  290. mono_gc_base_init ();
  291. mono_monitor_init ();
  292. mono_marshal_init ();
  293. mono_gc_init_icalls ();
  294. // We have to append here because otherwise this will run before the netcore hook (which is installed first), see https://github.com/dotnet/runtime/issues/34273
  295. mono_install_assembly_preload_hook_v2 (mono_domain_assembly_preload, GUINT_TO_POINTER (FALSE), FALSE, TRUE);
  296. mono_install_assembly_search_hook_v2 (mono_domain_assembly_search, GUINT_TO_POINTER (FALSE), FALSE, FALSE, FALSE);
  297. mono_install_assembly_search_hook_v2 (mono_domain_assembly_postload_search, GUINT_TO_POINTER (FALSE), FALSE, TRUE, FALSE);
  298. mono_install_assembly_load_hook_v2 (mono_domain_fire_assembly_load, NULL, FALSE);
  299. #ifndef ENABLE_NETCORE // refonly hooks
  300. mono_install_assembly_preload_hook_v2 (mono_domain_assembly_preload, GUINT_TO_POINTER (TRUE), TRUE, FALSE);
  301. mono_install_assembly_search_hook_v2 (mono_domain_assembly_search, GUINT_TO_POINTER (TRUE), TRUE, FALSE, FALSE);
  302. mono_install_assembly_search_hook_v2 (mono_domain_assembly_postload_search, GUINT_TO_POINTER (TRUE), TRUE, TRUE, FALSE);
  303. mono_install_assembly_asmctx_from_path_hook (mono_domain_asmctx_from_path, NULL);
  304. #endif
  305. mono_thread_init (start_cb, attach_cb);
  306. if (!mono_runtime_get_no_exec ()) {
  307. MonoClass *klass;
  308. #ifndef ENABLE_NETCORE
  309. klass = mono_class_get_appdomain_setup_class ();
  310. MonoAppDomainSetupHandle setup;
  311. setup = MONO_HANDLE_CAST (MonoAppDomainSetup, mono_object_new_pinned_handle (domain, klass, error));
  312. goto_if_nok (error, exit);
  313. #endif
  314. klass = mono_class_get_appdomain_class ();
  315. ad = MONO_HANDLE_CAST (MonoAppDomain, mono_object_new_pinned_handle (domain, klass, error));
  316. goto_if_nok (error, exit);
  317. #ifndef ENABLE_NETCORE
  318. MONO_HANDLE_SETVAL (ad, data, MonoDomain*, domain);
  319. #endif
  320. domain->domain = MONO_HANDLE_RAW (ad);
  321. #ifndef ENABLE_NETCORE
  322. mono_gc_wbarrier_generic_nostore_internal (&domain->domain);
  323. domain->setup = MONO_HANDLE_RAW (setup);
  324. mono_gc_wbarrier_generic_nostore_internal (&domain->setup);
  325. #endif
  326. }
  327. mono_thread_internal_attach (domain);
  328. #if defined(ENABLE_PERFTRACING) && !defined(DISABLE_EVENTPIPE)
  329. ds_server_init ();
  330. ds_server_pause_for_diagnostics_monitor ();
  331. #endif
  332. mono_type_initialization_init ();
  333. if (!mono_runtime_get_no_exec ())
  334. create_domain_objects (domain);
  335. /* GC init has to happen after thread init */
  336. mono_gc_init ();
  337. /* contexts use GC handles, so they must be initialized after the GC */
  338. #ifndef ENABLE_NETCORE
  339. mono_context_init_checked (domain, error);
  340. goto_if_nok (error, exit);
  341. mono_context_set_default_context (domain);
  342. #endif
  343. #ifdef ENABLE_NETCORE
  344. if (!mono_runtime_get_no_exec ())
  345. mono_runtime_install_appctx_properties ();
  346. #endif
  347. mono_network_init ();
  348. mono_console_init ();
  349. mono_attach_init ();
  350. mono_locks_tracer_init ();
  351. /* mscorlib is loaded before we install the load hook */
  352. mono_domain_fire_assembly_load (mono_domain_default_alc (domain), mono_defaults.corlib->assembly, NULL, error);
  353. goto_if_nok (error, exit);
  354. exit:
  355. HANDLE_FUNCTION_RETURN ();
  356. }
  357. static void
  358. mono_context_set_default_context (MonoDomain *domain)
  359. {
  360. if (mono_runtime_get_no_exec ())
  361. return;
  362. HANDLE_FUNCTION_ENTER ();
  363. mono_context_set_handle (MONO_HANDLE_NEW (MonoAppContext, domain->default_context));
  364. HANDLE_FUNCTION_RETURN ();
  365. }
  366. static char*
  367. mono_get_corlib_version (void)
  368. {
  369. ERROR_DECL (error);
  370. MonoClass *klass;
  371. MonoClassField *field;
  372. klass = mono_class_load_from_name (mono_defaults.corlib, "System", "Environment");
  373. mono_class_init_internal (klass);
  374. field = mono_class_get_field_from_name_full (klass, "mono_corlib_version", NULL);
  375. if (!field)
  376. return NULL;
  377. if (! (field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_LITERAL)))
  378. return NULL;
  379. char *value;
  380. MonoTypeEnum field_type;
  381. const char *data = mono_class_get_field_default_value (field, &field_type);
  382. if (field_type != MONO_TYPE_STRING)
  383. return NULL;
  384. mono_metadata_read_constant_value (data, field_type, &value, error);
  385. mono_error_assert_ok (error);
  386. char *res = mono_string_from_blob (value, error);
  387. mono_error_assert_ok (error);
  388. return res;
  389. }
  390. /**
  391. * mono_check_corlib_version:
  392. * Checks that the corlib that is loaded matches the version of this runtime.
  393. * \returns NULL if the runtime will work with the corlib, or a \c g_malloc
  394. * allocated string with the error otherwise.
  395. */
  396. const char*
  397. mono_check_corlib_version (void)
  398. {
  399. const char* res;
  400. MONO_ENTER_GC_UNSAFE;
  401. res = mono_check_corlib_version_internal ();
  402. MONO_EXIT_GC_UNSAFE;
  403. return res;
  404. }
  405. static const char *
  406. mono_check_corlib_version_internal (void)
  407. {
  408. #if defined(MONO_CROSS_COMPILE)
  409. /* Can't read the corlib version because we only have the target class layouts */
  410. return NULL;
  411. #else
  412. char *result = NULL;
  413. char *version = mono_get_corlib_version ();
  414. if (!version) {
  415. result = g_strdup_printf ("expected corlib string (%s) but not found or not string", MONO_CORLIB_VERSION);
  416. goto exit;
  417. }
  418. if (strcmp (version, MONO_CORLIB_VERSION) != 0) {
  419. result = g_strdup_printf ("The runtime did not find the mscorlib.dll it expected. "
  420. "Expected interface version %s but found %s. Check that "
  421. "your runtime and class libraries are matching.",
  422. MONO_CORLIB_VERSION, version);
  423. goto exit;
  424. }
  425. /* Check that the managed and unmanaged layout of MonoInternalThread matches */
  426. guint32 native_offset;
  427. guint32 managed_offset;
  428. native_offset = (guint32) MONO_STRUCT_OFFSET (MonoInternalThread, last);
  429. managed_offset = mono_field_get_offset (mono_class_get_field_from_name_full (mono_defaults.internal_thread_class, "last", NULL));
  430. if (native_offset != managed_offset)
  431. result = g_strdup_printf ("expected InternalThread.last field offset %u, found %u. See InternalThread.last comment", native_offset, managed_offset);
  432. exit:
  433. g_free (version);
  434. return result;
  435. #endif
  436. }
  437. /**
  438. * mono_context_init:
  439. * \param domain The domain where the \c System.Runtime.Remoting.Context.Context is initialized
  440. * Initializes the \p domain's default \c System.Runtime.Remoting 's Context.
  441. */
  442. void
  443. mono_context_init (MonoDomain *domain)
  444. {
  445. ERROR_DECL (error);
  446. mono_context_init_checked (domain, error);
  447. mono_error_cleanup (error);
  448. }
  449. void
  450. mono_context_init_checked (MonoDomain *domain, MonoError *error)
  451. {
  452. HANDLE_FUNCTION_ENTER ();
  453. MonoClass *klass;
  454. MonoAppContextHandle context;
  455. error_init (error);
  456. if (mono_runtime_get_no_exec ())
  457. goto exit;
  458. klass = mono_class_load_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Contexts", "Context");
  459. context = MONO_HANDLE_CAST (MonoAppContext, mono_object_new_pinned_handle (domain, klass, error));
  460. goto_if_nok (error, exit);
  461. MONO_HANDLE_SETVAL (context, domain_id, gint32, domain->domain_id);
  462. MONO_HANDLE_SETVAL (context, context_id, gint32, 0);
  463. mono_threads_register_app_context (context, error);
  464. mono_error_assert_ok (error);
  465. domain->default_context = MONO_HANDLE_RAW (context);
  466. exit:
  467. HANDLE_FUNCTION_RETURN ();
  468. }
  469. /**
  470. * mono_runtime_cleanup:
  471. * \param domain unused.
  472. *
  473. * Internal routine.
  474. *
  475. * This must not be called while there are still running threads executing
  476. * managed code.
  477. */
  478. void
  479. mono_runtime_cleanup (MonoDomain *domain)
  480. {
  481. mono_attach_cleanup ();
  482. /* This ends up calling any pending pending (for at most 2 seconds) */
  483. mono_gc_cleanup ();
  484. mono_thread_cleanup ();
  485. mono_network_cleanup ();
  486. mono_marshal_cleanup ();
  487. mono_type_initialization_cleanup ();
  488. mono_monitor_cleanup ();
  489. }
  490. static MonoDomainFunc quit_function = NULL;
  491. /**
  492. * mono_install_runtime_cleanup:
  493. */
  494. void
  495. mono_install_runtime_cleanup (MonoDomainFunc func)
  496. {
  497. quit_function = func;
  498. }
  499. /**
  500. * mono_runtime_quit:
  501. */
  502. void
  503. mono_runtime_quit (void)
  504. {
  505. MONO_STACKDATA (dummy);
  506. (void) mono_threads_enter_gc_unsafe_region_unbalanced_internal (&dummy);
  507. // after quit_function (in particular, mini_cleanup) everything is
  508. // cleaned up so MONO_EXIT_GC_UNSAFE can't work and doesn't make sense.
  509. mono_runtime_quit_internal ();
  510. }
  511. /**
  512. * mono_runtime_quit_internal:
  513. */
  514. void
  515. mono_runtime_quit_internal (void)
  516. {
  517. MONO_REQ_GC_UNSAFE_MODE;
  518. // but note that when we return, we're not in GC Unsafe mode anymore.
  519. // After clean up threads don't _have_ a thread state anymore.
  520. if (quit_function != NULL)
  521. quit_function (mono_get_root_domain (), NULL);
  522. }
  523. #ifndef ENABLE_NETCORE
  524. /**
  525. * mono_domain_create_appdomain:
  526. * \param friendly_name The friendly name of the appdomain to create
  527. * \param configuration_file The configuration file to initialize the appdomain with
  528. * \returns a \c MonoDomain initialized with the appdomain
  529. */
  530. MonoDomain *
  531. mono_domain_create_appdomain (char *friendly_name, char *configuration_file)
  532. {
  533. HANDLE_FUNCTION_ENTER ();
  534. MonoDomain *domain;
  535. MONO_ENTER_GC_UNSAFE;
  536. ERROR_DECL (error);
  537. domain = mono_domain_create_appdomain_checked (friendly_name, configuration_file, error);
  538. mono_error_cleanup (error);
  539. MONO_EXIT_GC_UNSAFE;
  540. HANDLE_FUNCTION_RETURN_VAL (domain);
  541. }
  542. /**
  543. * mono_domain_create_appdomain_checked:
  544. * \param friendly_name The friendly name of the appdomain to create
  545. * \param configuration_file The configuration file to initialize the appdomain with
  546. * \param error Set on error.
  547. *
  548. * \returns a MonoDomain initialized with the appdomain. On failure sets \p error and returns NULL.
  549. */
  550. MonoDomain *
  551. mono_domain_create_appdomain_checked (char *friendly_name, char *configuration_file, MonoError *error)
  552. {
  553. HANDLE_FUNCTION_ENTER ();
  554. error_init (error);
  555. MonoDomain *result = NULL;
  556. #ifndef ENABLE_NETCORE
  557. MonoClass *klass = mono_class_get_appdomain_setup_class ();
  558. MonoAppDomainSetupHandle setup = MONO_HANDLE_CAST (MonoAppDomainSetup, mono_object_new_handle (mono_domain_get (), klass, error));
  559. goto_if_nok (error, leave);
  560. MonoStringHandle config_file;
  561. if (configuration_file != NULL) {
  562. config_file = mono_string_new_handle (mono_domain_get (), configuration_file, error);
  563. goto_if_nok (error, leave);
  564. } else {
  565. config_file = MONO_HANDLE_NEW (MonoString, NULL);
  566. }
  567. MONO_HANDLE_SET (setup, configuration_file, config_file);
  568. #endif
  569. MonoAppDomainHandle ad;
  570. #ifndef ENABLE_NETCORE
  571. ad = mono_domain_create_appdomain_internal (friendly_name, setup, error);
  572. #else
  573. ad = MONO_HANDLE_CAST (MonoAppDomain, NULL_HANDLE);
  574. #endif
  575. goto_if_nok (error, leave);
  576. result = mono_domain_from_appdomain_handle (ad);
  577. leave:
  578. HANDLE_FUNCTION_RETURN_VAL (result);
  579. }
  580. #endif
  581. /**
  582. * mono_domain_set_config:
  583. * \param domain \c MonoDomain initialized with the appdomain we want to change
  584. * \param base_dir new base directory for the appdomain
  585. * \param config_file_name path to the new configuration for the app domain
  586. *
  587. * Used to set the system configuration for an appdomain
  588. *
  589. * Without using this, embedded builds will get 'System.Configuration.ConfigurationErrorsException:
  590. * Error Initializing the configuration system. ---> System.ArgumentException:
  591. * The 'ExeConfigFilename' argument cannot be null.' for some managed calls.
  592. */
  593. void
  594. mono_domain_set_config (MonoDomain *domain, const char *base_dir, const char *config_file_name)
  595. {
  596. #ifndef ENABLE_NETCORE
  597. HANDLE_FUNCTION_ENTER ();
  598. MONO_ENTER_GC_UNSAFE;
  599. ERROR_DECL (error);
  600. mono_domain_set_config_checked (domain, base_dir, config_file_name, error);
  601. mono_error_cleanup (error);
  602. MONO_EXIT_GC_UNSAFE;
  603. HANDLE_FUNCTION_RETURN ();
  604. #else
  605. g_assert_not_reached ();
  606. #endif
  607. }
  608. #ifndef ENABLE_NETCORE
  609. gboolean
  610. mono_domain_set_config_checked (MonoDomain *domain, const char *base_dir, const char *config_file_name, MonoError *error)
  611. {
  612. error_init (error);
  613. MonoAppDomainSetupHandle setup = MONO_HANDLE_NEW (MonoAppDomainSetup, domain->setup);
  614. MonoStringHandle base_dir_str = mono_string_new_handle (domain, base_dir, error);
  615. goto_if_nok (error, leave);
  616. MONO_HANDLE_SET (setup, application_base, base_dir_str);
  617. MonoStringHandle config_file_name_str;
  618. config_file_name_str = mono_string_new_handle (domain, config_file_name, error);
  619. goto_if_nok (error, leave);
  620. MONO_HANDLE_SET (setup, configuration_file, config_file_name_str);
  621. leave:
  622. return is_ok (error);
  623. }
  624. #endif
  625. #ifndef ENABLE_NETCORE
  626. static MonoAppDomainSetupHandle
  627. copy_app_domain_setup (MonoDomain *domain, MonoAppDomainSetupHandle setup, MonoError *error)
  628. {
  629. HANDLE_FUNCTION_ENTER ();
  630. MonoDomain *caller_domain;
  631. MonoClass *ads_class;
  632. MonoAppDomainSetupHandle result = MONO_HANDLE_NEW (MonoAppDomainSetup, NULL);
  633. error_init (error);
  634. caller_domain = mono_domain_get ();
  635. ads_class = mono_class_get_appdomain_setup_class ();
  636. MonoAppDomainSetupHandle copy = MONO_HANDLE_CAST (MonoAppDomainSetup, mono_object_new_handle(domain, ads_class, error));
  637. goto_if_nok (error, leave);
  638. mono_domain_set_internal_with_options (domain, TRUE);
  639. #define XCOPY_FIELD(type, dst, field, src, error) \
  640. do { \
  641. TYPED_HANDLE_NAME (type) src_val = MONO_HANDLE_NEW_GET (type, (src), field); \
  642. TYPED_HANDLE_NAME (type) copied_val = MONO_HANDLE_CAST (type, mono_marshal_xdomain_copy_value_handle (MONO_HANDLE_CAST (MonoObject, src_val), error)); \
  643. goto_if_nok (error, leave); \
  644. MONO_HANDLE_SET ((dst),field,copied_val); \
  645. } while (0)
  646. #define COPY_VAL(dst,field,type,src) \
  647. do { \
  648. MONO_HANDLE_SETVAL ((dst), field, type, MONO_HANDLE_GETVAL ((src),field)); \
  649. } while (0)
  650. XCOPY_FIELD (MonoString, copy, application_base, setup, error);
  651. XCOPY_FIELD (MonoString, copy, application_name, setup, error);
  652. XCOPY_FIELD (MonoString, copy, cache_path, setup, error);
  653. XCOPY_FIELD (MonoString, copy, configuration_file, setup, error);
  654. XCOPY_FIELD (MonoString, copy, dynamic_base, setup, error);
  655. XCOPY_FIELD (MonoString, copy, license_file, setup, error);
  656. XCOPY_FIELD (MonoString, copy, private_bin_path, setup, error);
  657. XCOPY_FIELD (MonoString, copy, private_bin_path_probe, setup, error);
  658. XCOPY_FIELD (MonoString, copy, shadow_copy_directories, setup, error);
  659. XCOPY_FIELD (MonoString, copy, shadow_copy_files, setup, error);
  660. COPY_VAL (copy, publisher_policy, MonoBoolean, setup);
  661. COPY_VAL (copy, path_changed, MonoBoolean, setup);
  662. COPY_VAL (copy, loader_optimization, int, setup);
  663. COPY_VAL (copy, disallow_binding_redirects, MonoBoolean, setup);
  664. COPY_VAL (copy, disallow_code_downloads, MonoBoolean, setup);
  665. XCOPY_FIELD (MonoArray, copy, domain_initializer_args, setup, error);
  666. COPY_VAL (copy, disallow_appbase_probe, MonoBoolean, setup);
  667. XCOPY_FIELD (MonoObject, copy, application_trust, setup, error);
  668. XCOPY_FIELD (MonoArray, copy, configuration_bytes, setup, error);
  669. XCOPY_FIELD (MonoArray, copy, serialized_non_primitives, setup, error);
  670. #undef XCOPY_FIELD
  671. #undef COPY_VAL
  672. mono_domain_set_internal_with_options (caller_domain, TRUE);
  673. MONO_HANDLE_ASSIGN (result, copy);
  674. leave:
  675. HANDLE_FUNCTION_RETURN_REF (MonoAppDomainSetup, result);
  676. }
  677. #endif
  678. #ifndef ENABLE_NETCORE
  679. static MonoAppDomainHandle
  680. mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetupHandle setup, MonoError *error)
  681. {
  682. HANDLE_FUNCTION_ENTER ();
  683. MonoAppDomainHandle result = MONO_HANDLE_NEW (MonoAppDomain, NULL);
  684. MonoClass *adclass;
  685. MonoDomain *data;
  686. error_init (error);
  687. adclass = mono_class_get_appdomain_class ();
  688. /* FIXME: pin all those objects */
  689. data = mono_domain_create();
  690. MonoAppDomainHandle ad = MONO_HANDLE_CAST (MonoAppDomain, mono_object_new_handle (data, adclass, error));
  691. goto_if_nok (error, leave);
  692. MONO_HANDLE_SETVAL (ad, data, MonoDomain*, data);
  693. data->domain = MONO_HANDLE_RAW (ad);
  694. mono_gc_wbarrier_generic_nostore_internal (&data->domain);
  695. data->friendly_name = g_strdup (friendly_name);
  696. MONO_PROFILER_RAISE (domain_name, (data, data->friendly_name));
  697. MonoStringHandle app_base;
  698. app_base = MONO_HANDLE_NEW_GET (MonoString, setup, application_base);
  699. if (MONO_HANDLE_IS_NULL (app_base)) {
  700. /* Inherit from the root domain since MS.NET does this */
  701. MonoDomain *root = mono_get_root_domain ();
  702. MonoAppDomainSetupHandle root_setup = MONO_HANDLE_NEW (MonoAppDomainSetup, root->setup);
  703. MonoStringHandle root_app_base = MONO_HANDLE_NEW_GET (MonoString, root_setup, application_base);
  704. if (!MONO_HANDLE_IS_NULL (root_app_base)) {
  705. /* N.B. new string is in the new domain */
  706. MonoGCHandle gchandle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, root_app_base), TRUE);
  707. MonoStringHandle s = mono_string_new_utf16_handle (data, mono_string_chars_internal (MONO_HANDLE_RAW (root_app_base)), mono_string_handle_length (root_app_base), error);
  708. mono_gchandle_free_internal (gchandle);
  709. if (!is_ok (error)) {
  710. g_free (data->friendly_name);
  711. goto leave;
  712. }
  713. MONO_HANDLE_SET (setup, application_base, s);
  714. }
  715. }
  716. mono_context_init_checked (data, error);
  717. goto_if_nok (error, leave);
  718. data->setup = MONO_HANDLE_RAW (copy_app_domain_setup (data, setup, error));
  719. mono_gc_wbarrier_generic_nostore_internal (&data->setup);
  720. if (!is_ok (error)) {
  721. g_free (data->friendly_name);
  722. goto leave;
  723. }
  724. mono_domain_set_options_from_config (data);
  725. add_assemblies_to_domain (data, mono_defaults.corlib->assembly, NULL);
  726. #ifndef DISABLE_SHADOW_COPY
  727. /*FIXME, guard this for when the debugger is not running */
  728. char *shadow_location;
  729. shadow_location = get_shadow_assembly_location_base (data, error);
  730. if (!is_ok (error)) {
  731. g_free (data->friendly_name);
  732. goto leave;
  733. }
  734. g_free (shadow_location);
  735. #endif
  736. create_domain_objects (data);
  737. MONO_HANDLE_ASSIGN (result, ad);
  738. leave:
  739. HANDLE_FUNCTION_RETURN_REF (MonoAppDomain, result);
  740. }
  741. #endif
  742. /**
  743. * mono_domain_has_type_resolve:
  744. * \param domain application domain being looked up
  745. *
  746. * \returns TRUE if the \c AppDomain.TypeResolve field has been set.
  747. */
  748. gboolean
  749. mono_domain_has_type_resolve (MonoDomain *domain)
  750. {
  751. // Check whether managed code is running, and if the managed AppDomain object doesn't exist neither does the event handler
  752. if (!domain->domain)
  753. return FALSE;
  754. #ifdef ENABLE_NETCORE
  755. return TRUE;
  756. #else
  757. MonoObject *o;
  758. MONO_STATIC_POINTER_INIT (MonoClassField, field)
  759. field = mono_class_get_field_from_name_full (mono_defaults.appdomain_class, "TypeResolve", NULL);
  760. g_assert (field);
  761. MONO_STATIC_POINTER_INIT_END (MonoClassField, field)
  762. mono_field_get_value_internal ((MonoObject*)(domain->domain), field, &o);
  763. return o != NULL;
  764. #endif
  765. }
  766. /**
  767. * mono_domain_try_type_resolve:
  768. * \param domain application domain in which to resolve the type
  769. * \param name the name of the type to resolve or NULL.
  770. * \param typebuilder A \c System.Reflection.Emit.TypeBuilder, used if name is NULL.
  771. *
  772. * This routine invokes the internal \c System.AppDomain.DoTypeResolve and returns
  773. * the assembly that matches name, or ((TypeBuilder)typebuilder).FullName.
  774. *
  775. * \returns A \c MonoReflectionAssembly or NULL if not found
  776. */
  777. MonoReflectionAssembly *
  778. mono_domain_try_type_resolve (MonoDomain *domain, char *name, MonoObject *typebuilder_raw)
  779. {
  780. HANDLE_FUNCTION_ENTER ();
  781. g_assert (domain);
  782. g_assert (name || typebuilder_raw);
  783. ERROR_DECL (error);
  784. MonoReflectionAssemblyHandle ret = NULL_HANDLE_INIT;
  785. // This will not work correctly on netcore
  786. if (name) {
  787. MonoStringHandle name_handle = mono_string_new_handle (mono_domain_get (), name, error);
  788. goto_if_nok (error, exit);
  789. ret = mono_domain_try_type_resolve_name (domain, NULL, name_handle, error);
  790. } else {
  791. #ifndef ENABLE_NETCORE
  792. MONO_HANDLE_DCL (MonoObject, typebuilder);
  793. ret = mono_domain_try_type_resolve_typebuilder (domain, MONO_HANDLE_CAST (MonoReflectionTypeBuilder, typebuilder), error);
  794. #else
  795. // TODO: make this work on netcore when working on SRE.TypeBuilder
  796. g_assert_not_reached ();
  797. #endif
  798. }
  799. exit:
  800. mono_error_cleanup (error);
  801. HANDLE_FUNCTION_RETURN_OBJ (ret);
  802. }
  803. #ifdef ENABLE_NETCORE
  804. MonoReflectionAssemblyHandle
  805. mono_domain_try_type_resolve_name (MonoDomain *domain, MonoAssembly *assembly, MonoStringHandle name, MonoError *error)
  806. {
  807. MonoObjectHandle ret;
  808. MonoReflectionAssemblyHandle assembly_handle;
  809. HANDLE_FUNCTION_ENTER ();
  810. MONO_STATIC_POINTER_INIT (MonoMethod, method)
  811. static gboolean inited;
  812. // avoid repeatedly calling mono_class_get_method_from_name_checked
  813. if (!inited) {
  814. ERROR_DECL (local_error);
  815. MonoClass *alc_class = mono_class_get_assembly_load_context_class ();
  816. g_assert (alc_class);
  817. method = mono_class_get_method_from_name_checked (alc_class, "OnTypeResolve", -1, 0, local_error);
  818. mono_error_cleanup (local_error);
  819. inited = TRUE;
  820. }
  821. MONO_STATIC_POINTER_INIT_END (MonoMethod, method)
  822. if (!method)
  823. goto return_null;
  824. g_assert (domain);
  825. g_assert (MONO_HANDLE_BOOL (name));
  826. if (mono_runtime_get_no_exec ())
  827. goto return_null;
  828. if (assembly) {
  829. assembly_handle = mono_assembly_get_object_handle (domain, assembly, error);
  830. goto_if_nok (error, return_null);
  831. }
  832. gpointer args [2];
  833. args [0] = assembly ? MONO_HANDLE_RAW (assembly_handle) : NULL;
  834. args [1] = MONO_HANDLE_RAW (name);
  835. ret = mono_runtime_try_invoke_handle (method, NULL_HANDLE, args, error);
  836. goto_if_nok (error, return_null);
  837. goto exit;
  838. return_null:
  839. ret = NULL_HANDLE;
  840. exit:
  841. HANDLE_FUNCTION_RETURN_REF (MonoReflectionAssembly, MONO_HANDLE_CAST (MonoReflectionAssembly, ret));
  842. }
  843. #else
  844. /**
  845. * mono_class_get_appdomain_do_type_resolve_method:
  846. *
  847. * This routine returns System.AppDomain.DoTypeResolve.
  848. */
  849. static MonoMethod *
  850. mono_class_get_appdomain_do_type_resolve_method (MonoError *error)
  851. {
  852. MONO_STATIC_POINTER_INIT (MonoMethod, method)
  853. method = mono_class_get_method_from_name_checked (mono_class_get_appdomain_class (), "DoTypeResolve", -1, 0, error);
  854. MONO_STATIC_POINTER_INIT_END (MonoMethod, method)
  855. if (method == NULL)
  856. g_warning ("%s method AppDomain.DoTypeResolve not found. %s\n", __func__, mono_error_get_message (error));
  857. return method;
  858. }
  859. /**
  860. * mono_class_get_appdomain_do_type_builder_resolve_method:
  861. *
  862. * This routine returns System.AppDomain.DoTypeBuilderResolve.
  863. */
  864. static MonoMethod *
  865. mono_class_get_appdomain_do_type_builder_resolve_method (MonoError *error)
  866. {
  867. MONO_STATIC_POINTER_INIT (MonoMethod, method)
  868. method = mono_class_get_method_from_name_checked (mono_class_get_appdomain_class (), "DoTypeBuilderResolve", -1, 0, error);
  869. MONO_STATIC_POINTER_INIT_END (MonoMethod, method)
  870. if (method == NULL)
  871. g_warning ("%s method AppDomain.DoTypeBuilderResolve not found. %s\n", __func__, mono_error_get_message (error));
  872. return method;
  873. }
  874. /**
  875. * mono_domain_try_type_resolve_name:
  876. * \param domain application domain in which to resolve the type
  877. * \param name the name of the type to resolve.
  878. *
  879. * This routine invokes the internal \c System.AppDomain.DoTypeResolve and returns
  880. * the assembly that matches name.
  881. *
  882. * \returns A \c MonoReflectionAssembly or NULL if not found
  883. */
  884. MonoReflectionAssemblyHandle
  885. mono_domain_try_type_resolve_name (MonoDomain *domain, MonoAssembly *assembly, MonoStringHandle name, MonoError *error)
  886. {
  887. HANDLE_FUNCTION_ENTER ();
  888. void *params [1] = { 0 };
  889. g_assert (domain);
  890. g_assert (MONO_HANDLE_BOOL (name));
  891. g_assert (error);
  892. error_init (error);
  893. MonoMethod *method;
  894. method = mono_class_get_appdomain_do_type_resolve_method (error);
  895. goto_if_nok (error, return_null);
  896. MonoAppDomainHandle appdomain;
  897. appdomain = MONO_HANDLE_NEW (MonoAppDomain, domain->domain);
  898. MonoObjectHandle ret;
  899. params [0] = MONO_HANDLE_RAW (name);
  900. ret = mono_runtime_invoke_handle (method, MONO_HANDLE_CAST (MonoObject, appdomain), params, error);
  901. goto_if_nok (error, return_null);
  902. goto exit;
  903. return_null:
  904. ret = NULL_HANDLE;
  905. exit:
  906. HANDLE_FUNCTION_RETURN_REF (MonoReflectionAssembly, MONO_HANDLE_CAST (MonoReflectionAssembly, ret));
  907. }
  908. /**
  909. * mono_domain_try_type_resolve_typebuilder:
  910. * \param domain application domain in which to resolve the type
  911. * \param typebuilder A \c System.Reflection.Emit.TypeBuilder; typebuilder.FullName is the name of the type to resolve.
  912. *
  913. * This routine invokes the internal \c System.AppDomain.DoTypeBuilderResolve and returns
  914. * the assembly that matches typebuilder.FullName.
  915. *
  916. * \returns A \c MonoReflectionAssembly or NULL_HANDLE if not found
  917. */
  918. MonoReflectionAssemblyHandle
  919. mono_domain_try_type_resolve_typebuilder (MonoDomain *domain, MonoReflectionTypeBuilderHandle typebuilder, MonoError *error)
  920. {
  921. HANDLE_FUNCTION_ENTER ();
  922. g_assert (domain);
  923. g_assert (MONO_HANDLE_BOOL (typebuilder));
  924. g_assert (error);
  925. error_init (error);
  926. MonoMethod * const method = mono_class_get_appdomain_do_type_builder_resolve_method (error);
  927. goto_if_nok (error, return_null);
  928. MonoAppDomainHandle appdomain;
  929. appdomain = MONO_HANDLE_NEW (MonoAppDomain, domain->domain);
  930. void *args [1];
  931. args [0] = MONO_HANDLE_RAW (typebuilder);
  932. MonoObjectHandle ret;
  933. ret = mono_runtime_invoke_handle (method, MONO_HANDLE_CAST (MonoObject, appdomain), args, error);
  934. goto_if_nok (error, return_null);
  935. goto exit;
  936. return_null:
  937. ret = NULL_HANDLE;
  938. exit:
  939. HANDLE_FUNCTION_RETURN_REF (MonoReflectionAssembly, MONO_HANDLE_CAST (MonoReflectionAssembly, ret));
  940. }
  941. #endif
  942. /**
  943. * mono_domain_owns_vtable_slot:
  944. * \returns Whether \p vtable_slot is inside a vtable which belongs to \p domain.
  945. */
  946. gboolean
  947. mono_domain_owns_vtable_slot (MonoDomain *domain, gpointer vtable_slot)
  948. {
  949. gboolean res;
  950. MonoMemoryManager *memory_manager = mono_domain_ambient_memory_manager (domain);
  951. mono_mem_manager_lock (memory_manager);
  952. res = mono_mempool_contains_addr (memory_manager->mp, vtable_slot);
  953. mono_mem_manager_unlock (memory_manager);
  954. return res;
  955. }
  956. gboolean
  957. mono_domain_set_fast (MonoDomain *domain, gboolean force)
  958. {
  959. MONO_REQ_GC_UNSAFE_MODE;
  960. if (!force && domain->state == MONO_APPDOMAIN_UNLOADED)
  961. return FALSE;
  962. mono_domain_set_internal_with_options (domain, TRUE);
  963. return TRUE;
  964. }
  965. #ifndef ENABLE_NETCORE
  966. MonoObjectHandle
  967. ves_icall_System_AppDomain_GetData (MonoAppDomainHandle ad, MonoStringHandle name, MonoError *error)
  968. {
  969. error_init (error);
  970. if (MONO_HANDLE_IS_NULL (name)) {
  971. mono_error_set_argument_null (error, "name", "");
  972. return NULL_HANDLE;
  973. }
  974. g_assert (!MONO_HANDLE_IS_NULL (ad));
  975. MonoDomain *add = MONO_HANDLE_GETVAL (ad, data);
  976. g_assert (add);
  977. char *str = mono_string_handle_to_utf8 (name, error);
  978. return_val_if_nok (error, NULL_HANDLE);
  979. mono_domain_lock (add);
  980. MonoAppDomainSetupHandle ad_setup = MONO_HANDLE_NEW (MonoAppDomainSetup, add->setup);
  981. MonoStringHandle o;
  982. if (!strcmp (str, "APPBASE"))
  983. o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, application_base);
  984. else if (!strcmp (str, "APP_CONFIG_FILE"))
  985. o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, configuration_file);
  986. else if (!strcmp (str, "DYNAMIC_BASE"))
  987. o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, dynamic_base);
  988. else if (!strcmp (str, "APP_NAME"))
  989. o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, application_name);
  990. else if (!strcmp (str, "CACHE_BASE"))
  991. o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, cache_path);
  992. else if (!strcmp (str, "PRIVATE_BINPATH"))
  993. o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, private_bin_path);
  994. else if (!strcmp (str, "BINPATH_PROBE_ONLY"))
  995. o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, private_bin_path_probe);
  996. else if (!strcmp (str, "SHADOW_COPY_DIRS"))
  997. o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, shadow_copy_directories);
  998. else if (!strcmp (str, "FORCE_CACHE_INSTALL"))
  999. o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, shadow_copy_files);
  1000. else
  1001. o = MONO_HANDLE_NEW (MonoString, (MonoString*)mono_g_hash_table_lookup (add->env, MONO_HANDLE_RAW (name)));
  1002. mono_domain_unlock (add);
  1003. g_free (str);
  1004. return MONO_HANDLE_CAST (MonoObject, o);
  1005. }
  1006. void
  1007. ves_icall_System_AppDomain_SetData (MonoAppDomainHandle ad, MonoStringHandle name, MonoObjectHandle data, MonoError *error)
  1008. {
  1009. error_init (error);
  1010. if (MONO_HANDLE_IS_NULL (name)) {
  1011. mono_error_set_argument_null (error, "name", "");
  1012. return;
  1013. }
  1014. g_assert (!MONO_HANDLE_IS_NULL (ad));
  1015. MonoDomain *add = MONO_HANDLE_GETVAL (ad, data);
  1016. g_assert (add);
  1017. mono_domain_lock (add);
  1018. mono_g_hash_table_insert_internal (add->env, MONO_HANDLE_RAW (name), MONO_HANDLE_RAW (data));
  1019. mono_domain_unlock (add);
  1020. }
  1021. #ifndef ENABLE_NETCORE
  1022. MonoAppDomainSetupHandle
  1023. ves_icall_System_AppDomain_getSetup (MonoAppDomainHandle ad, MonoError *error)
  1024. {
  1025. error_init (error);
  1026. g_assert (!MONO_HANDLE_IS_NULL (ad));
  1027. MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data);
  1028. g_assert (domain);
  1029. return MONO_HANDLE_NEW (MonoAppDomainSetup, domain->setup);
  1030. }
  1031. #endif
  1032. MonoStringHandle
  1033. ves_icall_System_AppDomain_getFriendlyName (MonoAppDomainHandle ad, MonoError *error)
  1034. {
  1035. error_init (error);
  1036. g_assert (!MONO_HANDLE_IS_NULL (ad));
  1037. MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data);
  1038. g_assert (domain);
  1039. return mono_string_new_handle (domain, domain->friendly_name, error);
  1040. }
  1041. MonoAppDomainHandle
  1042. ves_icall_System_AppDomain_getCurDomain (MonoError *error)
  1043. {
  1044. error_init (error);
  1045. MonoDomain *add = mono_domain_get ();
  1046. return MONO_HANDLE_NEW (MonoAppDomain, add->domain);
  1047. }
  1048. MonoAppDomainHandle
  1049. ves_icall_System_AppDomain_getRootDomain (MonoError *error)
  1050. {
  1051. error_init (error);
  1052. MonoDomain *root = mono_get_root_domain ();
  1053. return MONO_HANDLE_NEW (MonoAppDomain, root->domain);
  1054. }
  1055. MonoBoolean
  1056. ves_icall_System_CLRConfig_CheckThrowUnobservedTaskExceptions (MonoError *error)
  1057. {
  1058. MonoDomain *domain = mono_domain_get ();
  1059. return domain->throw_unobserved_task_exceptions;
  1060. }
  1061. #endif
  1062. #ifndef ENABLE_NETCORE
  1063. static char*
  1064. get_attribute_value (const gchar **attribute_names,
  1065. const gchar **attribute_values,
  1066. const char *att_name)
  1067. {
  1068. int n;
  1069. for (n = 0; attribute_names [n] != NULL; n++) {
  1070. if (strcmp (attribute_names [n], att_name) == 0)
  1071. return g_strdup (attribute_values [n]);
  1072. }
  1073. return NULL;
  1074. }
  1075. static void
  1076. start_element (GMarkupParseContext *context,
  1077. const gchar *element_name,
  1078. const gchar **attribute_names,
  1079. const gchar **attribute_values,
  1080. gpointer user_data,
  1081. GError **gerror)
  1082. {
  1083. RuntimeConfig *runtime_config = (RuntimeConfig *)user_data;
  1084. if (strcmp (element_name, "runtime") == 0) {
  1085. runtime_config->runtime_count++;
  1086. return;
  1087. }
  1088. if (strcmp (element_name, "assemblyBinding") == 0) {
  1089. runtime_config->assemblybinding_count++;
  1090. return;
  1091. }
  1092. if (runtime_config->runtime_count != 1)
  1093. return;
  1094. if (strcmp (element_name, "ThrowUnobservedTaskExceptions") == 0) {
  1095. const char *value = get_attribute_value (attribute_names, attribute_values, "enabled");
  1096. if (value && g_ascii_strcasecmp (value, "true") == 0)
  1097. runtime_config->domain->throw_unobserved_task_exceptions = TRUE;
  1098. }
  1099. if (runtime_config->assemblybinding_count != 1)
  1100. return;
  1101. if (strcmp (element_name, "probing") != 0)
  1102. return;
  1103. g_free (runtime_config->domain->private_bin_path);
  1104. runtime_config->domain->private_bin_path = get_attribute_value (attribute_names, attribute_values, "privatePath");
  1105. if (runtime_config->domain->private_bin_path && !runtime_config->domain->private_bin_path [0]) {
  1106. g_free (runtime_config->domain->private_bin_path);
  1107. runtime_config->domain->private_bin_path = NULL;
  1108. return;
  1109. }
  1110. }
  1111. static void
  1112. end_element (GMarkupParseContext *context,
  1113. const gchar *element_name,
  1114. gpointer user_data,
  1115. GError **gerror)
  1116. {
  1117. RuntimeConfig *runtime_config = (RuntimeConfig *)user_data;
  1118. if (strcmp (element_name, "runtime") == 0)
  1119. runtime_config->runtime_count--;
  1120. else if (strcmp (element_name, "assemblyBinding") == 0)
  1121. runtime_config->assemblybinding_count--;
  1122. }
  1123. static void
  1124. parse_error (GMarkupParseContext *context, GError *gerror, gpointer user_data)
  1125. {
  1126. RuntimeConfig *state = (RuntimeConfig *)user_data;
  1127. const gchar *msg;
  1128. const gchar *filename;
  1129. filename = state && state->filename ? (gchar *) state->filename : "<unknown>";
  1130. msg = gerror && gerror->message ? gerror->message : "";
  1131. g_warning ("Error parsing %s: %s", filename, msg);
  1132. }
  1133. static const GMarkupParser
  1134. mono_parser = {
  1135. start_element,
  1136. end_element,
  1137. NULL,
  1138. NULL,
  1139. parse_error
  1140. };
  1141. void
  1142. mono_domain_set_options_from_config (MonoDomain *domain)
  1143. {
  1144. ERROR_DECL (error);
  1145. gchar *config_file_name = NULL, *text = NULL, *config_file_path = NULL;
  1146. gsize len;
  1147. GMarkupParseContext *context;
  1148. RuntimeConfig runtime_config;
  1149. gint offset;
  1150. if (!domain || !domain->setup || !domain->setup->configuration_file)
  1151. return;
  1152. config_file_name = mono_string_to_utf8_checked_internal (domain->setup->configuration_file, error);
  1153. if (!is_ok (error)) {
  1154. mono_error_cleanup (error);
  1155. goto free_and_out;
  1156. }
  1157. config_file_path = mono_portability_find_file (config_file_name, TRUE);
  1158. if (!config_file_path)
  1159. config_file_path = config_file_name;
  1160. if (!g_file_get_contents (config_file_path, &text, &len, NULL))
  1161. goto free_and_out;
  1162. runtime_config.runtime_count = 0;
  1163. runtime_config.assemblybinding_count = 0;
  1164. runtime_config.domain = domain;
  1165. runtime_config.filename = config_file_path;
  1166. offset = 0;
  1167. if (len > 3 && text [0] == '\xef' && text [1] == (gchar) '\xbb' && text [2] == '\xbf')
  1168. offset = 3; /* Skip UTF-8 BOM */
  1169. context = g_markup_parse_context_new (&mono_parser, (GMarkupParseFlags)0, &runtime_config, NULL);
  1170. if (g_markup_parse_context_parse (context, text + offset, len - offset, NULL))
  1171. g_markup_parse_context_end_parse (context, NULL);
  1172. g_markup_parse_context_free (context);
  1173. free_and_out:
  1174. g_free (text);
  1175. if (config_file_name != config_file_path)
  1176. g_free (config_file_name);
  1177. g_free (config_file_path);
  1178. }
  1179. #endif
  1180. #ifndef ENABLE_NETCORE
  1181. MonoAppDomainHandle
  1182. ves_icall_System_AppDomain_createDomain (MonoStringHandle friendly_name, MonoAppDomainSetupHandle setup, MonoError *error)
  1183. {
  1184. error_init (error);
  1185. MonoAppDomainHandle ad = MONO_HANDLE_NEW (MonoAppDomain, NULL);
  1186. #ifdef DISABLE_APPDOMAINS
  1187. mono_error_set_not_supported (error, "AppDomain creation is not supported on this runtime.");
  1188. #else
  1189. char *fname;
  1190. fname = mono_string_handle_to_utf8 (friendly_name, error);
  1191. return_val_if_nok (error, ad);
  1192. ad = mono_domain_create_appdomain_internal (fname, setup, error);
  1193. g_free (fname);
  1194. #endif
  1195. return ad;
  1196. }
  1197. #endif
  1198. static gboolean
  1199. add_assembly_to_array (MonoDomain *domain, MonoArrayHandle dest, int dest_idx, MonoAssembly* assm, MonoError *error)
  1200. {
  1201. HANDLE_FUNCTION_ENTER ();
  1202. error_init (error);
  1203. MonoReflectionAssemblyHandle assm_obj = mono_assembly_get_object_handle (domain, assm, error);
  1204. goto_if_nok (error, leave);
  1205. MONO_HANDLE_ARRAY_SETREF (dest, dest_idx, assm_obj);
  1206. leave:
  1207. HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
  1208. }
  1209. static MonoArrayHandle
  1210. get_assembly_array_from_domain (MonoDomain *domain, MonoBoolean refonly, MonoError *error)
  1211. {
  1212. int i;
  1213. GPtrArray *assemblies;
  1214. assemblies = mono_domain_get_assemblies (domain, refonly);
  1215. MonoArrayHandle res = mono_array_new_handle (domain, mono_class_get_assembly_class (), assemblies->len, error);
  1216. goto_if_nok (error, leave);
  1217. for (i = 0; i < assemblies->len; ++i) {
  1218. if (!add_assembly_to_array (domain, res, i, (MonoAssembly *)g_ptr_array_index (assemblies, i), error))
  1219. goto leave;
  1220. }
  1221. leave:
  1222. g_ptr_array_free (assemblies, TRUE);
  1223. return res;
  1224. }
  1225. #ifdef ENABLE_NETCORE
  1226. MonoArrayHandle
  1227. ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalGetLoadedAssemblies (MonoError *error)
  1228. {
  1229. MonoDomain *domain = mono_domain_get ();
  1230. return get_assembly_array_from_domain (domain, FALSE, error);
  1231. }
  1232. #else
  1233. MonoArrayHandle
  1234. ves_icall_System_AppDomain_GetAssemblies (MonoAppDomainHandle ad, MonoBoolean refonly, MonoError *error)
  1235. {
  1236. MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data);
  1237. return get_assembly_array_from_domain (domain, refonly, error);
  1238. }
  1239. #endif
  1240. MonoAssembly*
  1241. mono_try_assembly_resolve (MonoAssemblyLoadContext *alc, const char *fname_raw, MonoAssembly *requesting, gboolean refonly, MonoError *error)
  1242. {
  1243. HANDLE_FUNCTION_ENTER ();
  1244. error_init (error);
  1245. MonoAssembly *result = NULL;
  1246. MonoStringHandle fname = mono_string_new_handle (mono_alc_domain (alc), fname_raw, error);
  1247. goto_if_nok (error, leave);
  1248. result = mono_try_assembly_resolve_handle (alc, fname, requesting, refonly, error);
  1249. leave:
  1250. HANDLE_FUNCTION_RETURN_VAL (result);
  1251. }
  1252. MonoAssembly*
  1253. mono_try_assembly_resolve_handle (MonoAssemblyLoadContext *alc, MonoStringHandle fname, MonoAssembly *requesting, gboolean refonly, MonoError *error)
  1254. {
  1255. HANDLE_FUNCTION_ENTER ();
  1256. MonoAssembly *ret = NULL;
  1257. MonoDomain *domain = mono_alc_domain (alc);
  1258. char *filename = NULL;
  1259. if (mono_runtime_get_no_exec ())
  1260. goto leave;
  1261. #ifndef ENABLE_NETCORE
  1262. static MonoMethod *method;
  1263. MonoBoolean isrefonly;
  1264. gpointer params [3];
  1265. g_assert (domain != NULL && !MONO_HANDLE_IS_NULL (fname));
  1266. // FIXME cache?
  1267. method = mono_class_get_method_from_name_checked (mono_class_get_appdomain_class (), "DoAssemblyResolve", -1, 0, error);
  1268. g_assert (method != NULL);
  1269. isrefonly = refonly ? 1 : 0;
  1270. MonoReflectionAssemblyHandle requesting_handle;
  1271. if (requesting) {
  1272. requesting_handle = mono_assembly_get_object_handle (domain, requesting, error);
  1273. goto_if_nok (error, leave);
  1274. }
  1275. params [0] = MONO_HANDLE_RAW (fname);
  1276. params [1] = requesting ? MONO_HANDLE_RAW (requesting_handle) : NULL;
  1277. params [2] = &isrefonly;
  1278. MonoObject *exc;
  1279. exc = NULL;
  1280. MonoReflectionAssemblyHandle result;
  1281. result = MONO_HANDLE_CAST (MonoReflectionAssembly, MONO_HANDLE_NEW (MonoObject, mono_runtime_try_invoke (method, domain->domain, params, &exc, error)));
  1282. if (!is_ok (error) || exc != NULL) {
  1283. if (is_ok (error))
  1284. mono_error_set_exception_instance (error, (MonoException*)exc);
  1285. goto leave;
  1286. }
  1287. ret = !MONO_HANDLE_IS_NULL (result) ? MONO_HANDLE_GETVAL (result, assembly) : NULL;
  1288. if (ret && !refonly && mono_asmctx_get_kind (&ret->context) == MONO_ASMCTX_REFONLY) {
  1289. /* .NET Framework throws System.IO.FileNotFoundException in this case */
  1290. filename = mono_string_handle_to_utf8 (fname, error);
  1291. mono_error_set_file_not_found (error, filename, "AssemblyResolveEvent handlers cannot return Assemblies loaded for reflection only: %s", filename);
  1292. ret = NULL;
  1293. goto leave;
  1294. }
  1295. #else
  1296. MONO_STATIC_POINTER_INIT (MonoMethod, method)
  1297. ERROR_DECL (local_error);
  1298. static gboolean inited;
  1299. if (!inited) {
  1300. MonoClass *alc_class = mono_class_get_assembly_load_context_class ();
  1301. g_assert (alc_class);
  1302. method = mono_class_get_method_from_name_checked (alc_class, "OnAssemblyResolve", -1, 0, local_error);
  1303. inited = TRUE;
  1304. }
  1305. mono_error_cleanup (local_error);
  1306. MONO_STATIC_POINTER_INIT_END (MonoMethod, method)
  1307. if (!method) {
  1308. ret = NULL;
  1309. goto leave;
  1310. }
  1311. MonoReflectionAssemblyHandle requesting_handle;
  1312. if (requesting) {
  1313. requesting_handle = mono_assembly_get_object_handle (domain, requesting, error);
  1314. goto_if_nok (error, leave);
  1315. }
  1316. gpointer params [2];
  1317. params [0] = requesting ? MONO_HANDLE_RAW (requesting_handle) : NULL;
  1318. params [1] = MONO_HANDLE_RAW (fname);
  1319. MonoReflectionAssemblyHandle result;
  1320. result = MONO_HANDLE_CAST (MonoReflectionAssembly, mono_runtime_try_invoke_handle (method, NULL_HANDLE, params, error));
  1321. goto_if_nok (error, leave);
  1322. if (MONO_HANDLE_BOOL (result))
  1323. ret = MONO_HANDLE_GETVAL (result, assembly);
  1324. #endif
  1325. leave:
  1326. g_free (filename);
  1327. HANDLE_FUNCTION_RETURN_VAL (ret);
  1328. }
  1329. MonoAssembly *
  1330. mono_domain_assembly_postload_search (MonoAssemblyLoadContext *alc, MonoAssembly *requesting,
  1331. MonoAssemblyName *aname,
  1332. gboolean refonly, gboolean postload,
  1333. gpointer user_data,
  1334. MonoError *error_out)
  1335. {
  1336. ERROR_DECL (error);
  1337. MonoAssembly *assembly;
  1338. char *aname_str;
  1339. aname_str = mono_stringify_assembly_name (aname);
  1340. /* FIXME: We invoke managed code here, so there is a potential for deadlocks */
  1341. assembly = mono_try_assembly_resolve (alc, aname_str, requesting, refonly, error);
  1342. g_free (aname_str);
  1343. mono_error_cleanup (error);
  1344. return assembly;
  1345. }
  1346. /*
  1347. * LOCKING: assumes assemblies_lock in the domain is already locked.
  1348. */
  1349. static void
  1350. add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *ht)
  1351. {
  1352. GSList *tmp;
  1353. gboolean destroy_ht = FALSE;
  1354. g_assert (ass != NULL);
  1355. if (!ass->aname.name)
  1356. return;
  1357. if (!ht) {
  1358. ht = g_hash_table_new (mono_aligned_addr_hash, NULL);
  1359. destroy_ht = TRUE;
  1360. for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
  1361. g_hash_table_add (ht, tmp->data);
  1362. }
  1363. }
  1364. if (!g_hash_table_lookup (ht, ass)) {
  1365. mono_assembly_addref (ass);
  1366. g_hash_table_add (ht, ass);
  1367. domain->domain_assemblies = g_slist_append (domain->domain_assemblies, ass);
  1368. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly %s[%p] added to domain %s, ref_count=%d", ass->aname.name, ass, domain->friendly_name, ass->ref_count);
  1369. }
  1370. #ifndef ENABLE_NETCORE
  1371. if (ass->image->references) {
  1372. for (int i = 0; i < ass->image->nreferences; i++) {
  1373. MonoAssembly *ref = ass->image->references [i];
  1374. if (ref && ref != REFERENCE_MISSING) {
  1375. if (!g_hash_table_lookup (ht, ref))
  1376. add_assemblies_to_domain (domain, ref, ht);
  1377. }
  1378. }
  1379. }
  1380. #endif
  1381. if (destroy_ht)
  1382. g_hash_table_destroy (ht);
  1383. }
  1384. /*
  1385. * LOCKING: assumes the ALC's assemblies lock is taken
  1386. */
  1387. #ifdef ENABLE_NETCORE
  1388. static void
  1389. add_assembly_to_alc (MonoAssemblyLoadContext *alc, MonoAssembly *ass)
  1390. {
  1391. GSList *tmp;
  1392. g_assert (ass != NULL);
  1393. if (!ass->aname.name)
  1394. return;
  1395. for (tmp = alc->loaded_assemblies; tmp; tmp = tmp->next) {
  1396. if (tmp->data == ass) {
  1397. return;
  1398. }
  1399. }
  1400. mono_assembly_addref (ass);
  1401. // Prepending here will break the test suite with frequent InvalidCastExceptions, so we have to append
  1402. alc->loaded_assemblies = g_slist_append (alc->loaded_assemblies, ass);
  1403. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly %s[%p] added to ALC (%p), ref_count=%d", ass->aname.name, ass, (gpointer)alc, ass->ref_count);
  1404. }
  1405. #endif
  1406. static void
  1407. mono_domain_fire_assembly_load_event (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
  1408. {
  1409. HANDLE_FUNCTION_ENTER ();
  1410. g_assert (domain);
  1411. g_assert (assembly);
  1412. #ifdef ENABLE_NETCORE
  1413. MONO_STATIC_POINTER_INIT (MonoMethod, method)
  1414. static gboolean inited;
  1415. if (!inited) {
  1416. ERROR_DECL (local_error);
  1417. MonoClass *alc_class = mono_class_get_assembly_load_context_class ();
  1418. g_assert (alc_class);
  1419. method = mono_class_get_method_from_name_checked (alc_class, "OnAssemblyLoad", -1, 0, local_error);
  1420. mono_error_cleanup (local_error);
  1421. inited = TRUE;
  1422. }
  1423. MONO_STATIC_POINTER_INIT_END (MonoMethod, method)
  1424. if (!method)
  1425. goto exit;
  1426. MonoReflectionAssemblyHandle assembly_handle;
  1427. assembly_handle = mono_assembly_get_object_handle (domain, assembly, error);
  1428. goto_if_nok (error, exit);
  1429. gpointer args [1];
  1430. args [0] = MONO_HANDLE_RAW (assembly_handle);
  1431. mono_runtime_try_invoke_handle (method, NULL_HANDLE, args, error);
  1432. #else
  1433. MonoObjectHandle appdomain = MONO_HANDLE_NEW (MonoObject, &domain->domain->mbr.obj);
  1434. MonoClass *klass = mono_handle_class (appdomain);
  1435. MONO_STATIC_POINTER_INIT (MonoClassField, assembly_load_field)
  1436. assembly_load_field = mono_class_get_field_from_name_full (klass, "AssemblyLoad", NULL);
  1437. g_assert (assembly_load_field);
  1438. MONO_STATIC_POINTER_INIT_END (MonoClassField, assembly_load_field)
  1439. if (!MONO_HANDLE_GET_FIELD_BOOL (appdomain, MonoObject*, assembly_load_field))
  1440. goto exit; // No events waiting to be triggered
  1441. MonoReflectionAssemblyHandle reflection_assembly;
  1442. reflection_assembly = mono_assembly_get_object_handle (domain, assembly, error);
  1443. goto_if_nok (error, exit);
  1444. MONO_STATIC_POINTER_INIT (MonoMethod, assembly_load_method)
  1445. assembly_load_method = mono_class_get_method_from_name_checked (klass, "DoAssemblyLoad", -1, 0, error);
  1446. g_assert (assembly_load_method);
  1447. MONO_STATIC_POINTER_INIT_END (MonoMethod, assembly_load_method)
  1448. void *params [1];
  1449. params [0] = MONO_HANDLE_RAW (reflection_assembly);
  1450. mono_runtime_invoke_handle_void (assembly_load_method, appdomain, params, error);
  1451. #endif
  1452. exit:
  1453. HANDLE_FUNCTION_RETURN ();
  1454. }
  1455. static void
  1456. mono_domain_fire_assembly_load (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer user_data, MonoError *error_out)
  1457. {
  1458. ERROR_DECL (error);
  1459. MonoDomain *domain = mono_alc_domain (alc);
  1460. g_assert (assembly);
  1461. g_assert (domain);
  1462. if (!MONO_BOOL (domain->domain))
  1463. goto leave; // This can happen during startup
  1464. if (mono_runtime_get_no_exec ())
  1465. goto leave;
  1466. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Loading assembly %s (%p) into domain %s (%p) and ALC %p", assembly->aname.name, assembly, domain->friendly_name, domain, alc);
  1467. mono_domain_assemblies_lock (domain);
  1468. #ifdef ENABLE_NETCORE
  1469. mono_alc_assemblies_lock (alc);
  1470. #endif
  1471. add_assemblies_to_domain (domain, assembly, NULL);
  1472. #ifdef ENABLE_NETCORE
  1473. add_assembly_to_alc (alc, assembly);
  1474. mono_alc_assemblies_unlock (alc);
  1475. #endif
  1476. mono_domain_assemblies_unlock (domain);
  1477. if (assembly->context.kind != MONO_ASMCTX_INTERNAL)
  1478. mono_domain_fire_assembly_load_event (domain, assembly, error_out);
  1479. leave:
  1480. mono_error_cleanup (error);
  1481. }
  1482. static gboolean
  1483. mono_domain_asmctx_from_path (const char *fname, MonoAssembly *requesting_assembly, gpointer user_data, MonoAssemblyContextKind *out_asmctx)
  1484. {
  1485. MonoDomain *domain = mono_domain_get ();
  1486. char **search_path = NULL;
  1487. for (search_path = domain->search_path; search_path && *search_path; search_path++) {
  1488. if (mono_path_filename_in_basedir (fname, *search_path)) {
  1489. *out_asmctx = MONO_ASMCTX_DEFAULT;
  1490. return TRUE;
  1491. }
  1492. }
  1493. return FALSE;
  1494. }
  1495. #ifndef ENABLE_NETCORE
  1496. /*
  1497. * LOCKING: Acquires the domain assemblies lock.
  1498. */
  1499. static void
  1500. set_domain_search_path (MonoDomain *domain)
  1501. {
  1502. HANDLE_FUNCTION_ENTER ();
  1503. ERROR_DECL (error);
  1504. MonoAppDomainSetupHandle setup;
  1505. gchar **tmp;
  1506. gchar *search_path = NULL;
  1507. gint npaths = 1;
  1508. gchar **pvt_split = NULL;
  1509. GError *gerror = NULL;
  1510. gint appbaselen = -1;
  1511. /*
  1512. * We use the low-level domain assemblies lock, since this is called from
  1513. * assembly loads hooks, which means this thread might hold the loader lock.
  1514. */
  1515. mono_domain_assemblies_lock (domain);
  1516. if (!MONO_BOOL (domain->setup))
  1517. goto exit;
  1518. setup = MONO_HANDLE_NEW (MonoAppDomainSetup, domain->setup);
  1519. if (domain->search_path && !MONO_HANDLE_GET_BOOL (setup, path_changed))
  1520. goto exit;
  1521. if (!MONO_HANDLE_GET_BOOL (setup, application_base))
  1522. goto exit; // Must set application base to get private path working
  1523. if (MONO_HANDLE_GET_BOOL (setup, private_bin_path)) {
  1524. search_path = mono_string_handle_to_utf8 (MONO_HANDLE_NEW_GET (MonoString, setup, private_bin_path), error);
  1525. if (!is_ok (error)) { /*FIXME maybe we should bubble up the error.*/
  1526. g_warning ("Could not decode AppDomain search path since it contains invalid characters");
  1527. goto exit;
  1528. }
  1529. }
  1530. if (domain->private_bin_path) {
  1531. if (search_path == NULL)
  1532. search_path = domain->private_bin_path;
  1533. else {
  1534. gchar *tmp2 = search_path;
  1535. search_path = g_strjoin (";", search_path, domain->private_bin_path, (const char*)NULL);
  1536. g_free (tmp2);
  1537. }
  1538. }
  1539. if (search_path) {
  1540. /*
  1541. * As per MSDN documentation, AppDomainSetup.PrivateBinPath contains a list of
  1542. * directories relative to ApplicationBase separated by semicolons (see
  1543. * http://msdn2.microsoft.com/en-us/library/system.appdomainsetup.privatebinpath.aspx)
  1544. * The loop below copes with the fact that some Unix applications may use ':' (or
  1545. * System.IO.Path.PathSeparator) as the path search separator. We replace it with
  1546. * ';' for the subsequent split.
  1547. *
  1548. * The issue was reported in bug #81446
  1549. */
  1550. #ifndef TARGET_WIN32
  1551. g_strdelimit (search_path, ':', ';');
  1552. #endif
  1553. pvt_split = g_strsplit (search_path, ";", 1000);
  1554. g_free (search_path);
  1555. for (tmp = pvt_split; *tmp; tmp++, npaths++);
  1556. }
  1557. g_strfreev (domain->search_path);
  1558. domain->search_path = NULL;
  1559. tmp = g_new (gchar*, npaths + 1);
  1560. tmp [npaths] = NULL;
  1561. *tmp = mono_string_handle_to_utf8 (MONO_HANDLE_NEW_GET (MonoString, setup, application_base), error);
  1562. if (!is_ok (error)) {
  1563. g_free (tmp);
  1564. goto exit;
  1565. }
  1566. domain->search_path = tmp;
  1567. /* FIXME: is this needed? */
  1568. if (strncmp (*tmp, "file://", 7) == 0) {
  1569. gchar *file = *tmp;
  1570. gchar *uri = *tmp;
  1571. gchar *tmpuri;
  1572. if (uri [7] != '/')
  1573. uri = g_strdup_printf ("file:///%s", uri + 7);
  1574. tmpuri = uri;
  1575. uri = mono_escape_uri_string (tmpuri);
  1576. *tmp = g_filename_from_uri (uri, NULL, &gerror);
  1577. g_free (uri);
  1578. if (tmpuri != file)
  1579. g_free (tmpuri);
  1580. if (gerror != NULL) {
  1581. g_warning ("%s\n", gerror->message);
  1582. g_error_free (gerror);
  1583. *tmp = file;
  1584. } else {
  1585. g_free (file);
  1586. }
  1587. }
  1588. for (gsize i = 1; pvt_split && i < npaths; i++) {
  1589. if (g_path_is_absolute (pvt_split [i - 1])) {
  1590. tmp [i] = g_strdup (pvt_split [i - 1]);
  1591. } else {
  1592. tmp [i] = g_build_filename (tmp [0], pvt_split [i - 1], (const char*)NULL);
  1593. }
  1594. if (strchr (tmp [i], '.')) {
  1595. gchar *reduced;
  1596. gchar *freeme;
  1597. reduced = mono_path_canonicalize (tmp [i]);
  1598. if (appbaselen == -1)
  1599. appbaselen = strlen (tmp [0]);
  1600. if (strncmp (tmp [0], reduced, appbaselen)) {
  1601. g_free (reduced);
  1602. g_free (tmp [i]);
  1603. tmp [i] = g_strdup ("");
  1604. continue;
  1605. }
  1606. freeme = tmp [i];
  1607. tmp [i] = reduced;
  1608. g_free (freeme);
  1609. }
  1610. }
  1611. if (MONO_HANDLE_GET_BOOL (setup, private_bin_path_probe)) {
  1612. g_free (tmp [0]);
  1613. tmp [0] = g_strdup ("");
  1614. }
  1615. MONO_HANDLE_SETVAL (setup, path_changed, MonoBoolean, FALSE);
  1616. exit:
  1617. mono_error_cleanup (error);
  1618. g_strfreev (pvt_split);
  1619. mono_domain_assemblies_unlock (domain);
  1620. HANDLE_FUNCTION_RETURN ();
  1621. }
  1622. #endif
  1623. #ifdef DISABLE_SHADOW_COPY
  1624. gboolean
  1625. mono_is_shadow_copy_enabled (MonoDomain *domain, const gchar *dir_name)
  1626. {
  1627. return FALSE;
  1628. }
  1629. char *
  1630. mono_make_shadow_copy (const char *filename, MonoError *error)
  1631. {
  1632. error_init (error);
  1633. return (char *) filename;
  1634. }
  1635. #else
  1636. typedef enum {
  1637. SHADOW_COPY_SIBLING_EXT_APPEND,
  1638. SHADOW_COPY_SIBLING_EXT_REPLACE,
  1639. } ShadowCopySiblingExt;
  1640. static
  1641. gchar *
  1642. make_sibling_path (const gchar *path, gint pathlen, const char *extension, ShadowCopySiblingExt extopt)
  1643. {
  1644. gchar *result = NULL;
  1645. switch (extopt) {
  1646. case SHADOW_COPY_SIBLING_EXT_APPEND: {
  1647. result = g_strconcat (path, extension, (const char*)NULL);
  1648. break;
  1649. }
  1650. case SHADOW_COPY_SIBLING_EXT_REPLACE: {
  1651. /* expect path to be a .dll or .exe (or some case insensitive variant) */
  1652. g_assert (pathlen >= 4 && path[pathlen - 4] == '.');
  1653. GString *s = g_string_sized_new (pathlen - 4 + strlen (extension));
  1654. g_string_append_len (s, path, pathlen - 4);
  1655. g_string_append (s, extension);
  1656. result = g_string_free (s, FALSE);
  1657. break;
  1658. }
  1659. default:
  1660. g_assert_not_reached ();
  1661. }
  1662. return result;
  1663. }
  1664. static gboolean
  1665. shadow_copy_sibling (const gchar *src_pristine, gint srclen, const char *extension, ShadowCopySiblingExt extopt, const gchar *target_pristine, gint targetlen)
  1666. {
  1667. gchar *file = NULL;
  1668. gunichar2 *orig = NULL;
  1669. gunichar2 *dest = NULL;
  1670. gboolean copy_result = TRUE;
  1671. gchar *target = NULL;
  1672. char *src = make_sibling_path (src_pristine, srclen, extension, extopt);
  1673. if (IS_PORTABILITY_CASE) {
  1674. file = mono_portability_find_file (src, TRUE);
  1675. if (file == NULL)
  1676. goto exit;
  1677. } else if (!g_file_test (src, G_FILE_TEST_IS_REGULAR))
  1678. goto exit;
  1679. orig = g_utf8_to_utf16 (src, strlen (src), NULL, NULL, NULL);
  1680. target = make_sibling_path (target_pristine, targetlen, extension, extopt);
  1681. dest = g_utf8_to_utf16 (target, strlen (target), NULL, NULL, NULL);
  1682. mono_w32file_delete (dest);
  1683. gint32 copy_error;
  1684. copy_result = mono_w32file_copy (orig, dest, TRUE, &copy_error);
  1685. /* Fix for bug #556884 - make sure the files have the correct mode so that they can be
  1686. * overwritten when updated in their original locations. */
  1687. if (copy_result)
  1688. copy_result = mono_w32file_set_attributes (dest, FILE_ATTRIBUTE_NORMAL);
  1689. exit:
  1690. g_free (file);
  1691. g_free (orig);
  1692. g_free (dest);
  1693. g_free (src);
  1694. g_free (target);
  1695. return copy_result;
  1696. }
  1697. static gint32
  1698. get_cstring_hash (const char *str)
  1699. {
  1700. const char *p;
  1701. gint32 h = 0;
  1702. if (!str || !str [0])
  1703. return 0;
  1704. gsize const len = strlen (str);
  1705. p = str;
  1706. for (gsize i = 0; i < len; i++) {
  1707. h = (h << 5) - h + *p;
  1708. p++;
  1709. }
  1710. return h;
  1711. }
  1712. /*
  1713. * Returned memory is malloc'd. Called must free it
  1714. */
  1715. static char *
  1716. get_shadow_assembly_location_base (MonoDomain *domain, MonoError *error)
  1717. {
  1718. MonoAppDomainSetup *setup;
  1719. char *cache_path = NULL;
  1720. char *appname = NULL;
  1721. char *userdir = NULL;
  1722. char *location;
  1723. error_init (error);
  1724. setup = domain->setup;
  1725. if (setup->cache_path != NULL && setup->application_name != NULL) {
  1726. cache_path = mono_string_to_utf8_checked_internal (setup->cache_path, error);
  1727. return_val_if_nok (error, NULL);
  1728. #ifndef TARGET_WIN32
  1729. {
  1730. gint i;
  1731. for (i = strlen (cache_path) - 1; i >= 0; i--)
  1732. if (cache_path [i] == '\\')
  1733. cache_path [i] = '/';
  1734. }
  1735. #endif
  1736. appname = mono_string_to_utf8_checked_internal (setup->application_name, error);
  1737. if (!is_ok (error)) {
  1738. g_free (cache_path);
  1739. return NULL;
  1740. }
  1741. location = g_build_filename (cache_path, appname, "assembly", "shadow", (const char*)NULL);
  1742. } else {
  1743. userdir = g_strdup_printf ("%s-mono-cachepath", g_get_user_name ());
  1744. location = g_build_filename (g_get_tmp_dir (), userdir, "assembly", "shadow", (const char*)NULL);
  1745. }
  1746. g_free (appname);
  1747. g_free (cache_path);
  1748. g_free (userdir);
  1749. return location;
  1750. }
  1751. static char *
  1752. get_shadow_assembly_location (const char *filename, MonoError *error)
  1753. {
  1754. gint32 hash = 0, hash2 = 0;
  1755. char name_hash [9];
  1756. char path_hash [30];
  1757. char *bname = g_path_get_basename (filename);
  1758. char *dirname = g_path_get_dirname (filename);
  1759. char *location, *tmploc;
  1760. MonoDomain *domain = mono_domain_get ();
  1761. error_init (error);
  1762. hash = get_cstring_hash (bname);
  1763. hash2 = get_cstring_hash (dirname);
  1764. g_snprintf (name_hash, sizeof (name_hash), "%08x", hash);
  1765. g_snprintf (path_hash, sizeof (path_hash), "%08x_%08x_%08x", hash ^ hash2, hash2, domain->shadow_serial);
  1766. tmploc = get_shadow_assembly_location_base (domain, error);
  1767. if (!is_ok (error)) {
  1768. g_free (bname);
  1769. g_free (dirname);
  1770. return NULL;
  1771. }
  1772. location = g_build_filename (tmploc, name_hash, path_hash, bname, (const char*)NULL);
  1773. g_free (tmploc);
  1774. g_free (bname);
  1775. g_free (dirname);
  1776. return location;
  1777. }
  1778. static gboolean
  1779. private_file_needs_copying (const char *src, struct stat *sbuf_src, char *dest)
  1780. {
  1781. struct stat sbuf_dest;
  1782. gchar *stat_src;
  1783. gchar *real_src = mono_portability_find_file (src, TRUE);
  1784. if (!real_src)
  1785. stat_src = (gchar*)src;
  1786. else
  1787. stat_src = real_src;
  1788. if (stat (stat_src, sbuf_src) == -1) {
  1789. time_t tnow = time (NULL);
  1790. if (real_src)
  1791. g_free (real_src);
  1792. memset (sbuf_src, 0, sizeof (*sbuf_src));
  1793. sbuf_src->st_mtime = tnow;
  1794. sbuf_src->st_atime = tnow;
  1795. return TRUE;
  1796. }
  1797. if (real_src)
  1798. g_free (real_src);
  1799. if (stat (dest, &sbuf_dest) == -1)
  1800. return TRUE;
  1801. if (sbuf_src->st_size == sbuf_dest.st_size &&
  1802. sbuf_src->st_mtime == sbuf_dest.st_mtime)
  1803. return FALSE;
  1804. return TRUE;
  1805. }
  1806. static gboolean
  1807. shadow_copy_create_ini (const char *shadow, const char *filename)
  1808. {
  1809. gunichar2 *u16_ini = NULL;
  1810. gboolean result = FALSE;
  1811. guint32 n;
  1812. HANDLE handle = INVALID_HANDLE_VALUE;
  1813. gchar *full_path = NULL;
  1814. char *dir_name = g_path_get_dirname (shadow);
  1815. char *ini_file = g_build_filename (dir_name, "__AssemblyInfo__.ini", (const char*)NULL);
  1816. g_free (dir_name);
  1817. result = g_file_test (ini_file, G_FILE_TEST_IS_REGULAR);
  1818. if (result)
  1819. goto exit;
  1820. u16_ini = g_utf8_to_utf16 (ini_file, strlen (ini_file), NULL, NULL, NULL);
  1821. if (!u16_ini)
  1822. goto exit;
  1823. handle = mono_w32file_create (u16_ini, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, CREATE_NEW, FileAttributes_Normal);
  1824. if (handle == INVALID_HANDLE_VALUE)
  1825. goto exit;
  1826. full_path = mono_path_resolve_symlinks (filename);
  1827. gint32 win32error;
  1828. win32error = 0;
  1829. result = mono_w32file_write (handle, full_path, strlen (full_path), &n, &win32error);
  1830. exit:
  1831. if (handle != INVALID_HANDLE_VALUE)
  1832. mono_w32file_close (handle);
  1833. g_free (u16_ini);
  1834. g_free (full_path);
  1835. g_free (ini_file);
  1836. return result;
  1837. }
  1838. gboolean
  1839. mono_is_shadow_copy_enabled (MonoDomain *domain, const gchar *dir_name)
  1840. {
  1841. ERROR_DECL (error);
  1842. MonoAppDomainSetup *setup;
  1843. gchar *all_dirs = NULL;
  1844. gchar **dir_ptr;
  1845. gchar **directories = NULL;
  1846. gchar *shadow_status_string;
  1847. gchar *base_dir = NULL;
  1848. gboolean shadow_enabled;
  1849. gboolean found = FALSE;
  1850. if (domain == NULL)
  1851. goto exit;
  1852. setup = domain->setup;
  1853. if (setup == NULL || setup->shadow_copy_files == NULL)
  1854. goto exit;
  1855. shadow_status_string = mono_string_to_utf8_checked_internal (setup->shadow_copy_files, error);
  1856. if (!is_ok (error))
  1857. goto exit;
  1858. shadow_enabled = !g_ascii_strncasecmp (shadow_status_string, "true", 4);
  1859. g_free (shadow_status_string);
  1860. if (!shadow_enabled)
  1861. goto exit;
  1862. found = (setup->shadow_copy_directories == NULL);
  1863. if (found)
  1864. goto exit;
  1865. /* Is dir_name a shadow_copy destination already? */
  1866. base_dir = get_shadow_assembly_location_base (domain, error);
  1867. if (!is_ok (error))
  1868. goto exit;
  1869. found = strstr (dir_name, base_dir) != 0;
  1870. if (found)
  1871. goto exit;
  1872. all_dirs = mono_string_to_utf8_checked_internal (setup->shadow_copy_directories, error);
  1873. if (!is_ok (error))
  1874. goto exit;
  1875. directories = g_strsplit (all_dirs, G_SEARCHPATH_SEPARATOR_S, 1000);
  1876. dir_ptr = directories;
  1877. while (!found && *dir_ptr) {
  1878. found = (**dir_ptr != '\0' && !strcmp (*dir_ptr, dir_name));
  1879. dir_ptr++;
  1880. }
  1881. exit:
  1882. mono_error_cleanup (error);
  1883. g_free (base_dir);
  1884. g_strfreev (directories);
  1885. g_free (all_dirs);
  1886. return found;
  1887. }
  1888. /*
  1889. This function raises exceptions so it can cause as sorts of nasty stuff if called
  1890. while holding a lock.
  1891. Returns old file name if shadow copy is disabled, new shadow copy file name if successful
  1892. or NULL if source file not found.
  1893. FIXME bubble up the error instead of raising it here
  1894. */
  1895. char *
  1896. mono_make_shadow_copy (const char *filename, MonoError *oerror)
  1897. {
  1898. ERROR_DECL (error);
  1899. gint filename_len, shadow_len;
  1900. gunichar2 *orig, *dest;
  1901. guint32 attrs;
  1902. char *shadow;
  1903. gboolean copy_result;
  1904. struct stat src_sbuf;
  1905. struct utimbuf utbuf;
  1906. char *dir_name = g_path_get_dirname (filename);
  1907. MonoDomain *domain = mono_domain_get ();
  1908. char *shadow_dir;
  1909. gint32 copy_error;
  1910. #ifndef ENABLE_NETCORE
  1911. set_domain_search_path (domain);
  1912. #endif
  1913. if (!mono_is_shadow_copy_enabled (domain, dir_name)) {
  1914. g_free (dir_name);
  1915. return (char *) filename;
  1916. }
  1917. /* Is dir_name a shadow_copy destination already? */
  1918. shadow_dir = get_shadow_assembly_location_base (domain, error);
  1919. if (!is_ok (error)) {
  1920. mono_error_cleanup (error);
  1921. g_free (dir_name);
  1922. mono_error_set_execution_engine (oerror, "Failed to create shadow copy (invalid characters in shadow directory name).");
  1923. return NULL;
  1924. }
  1925. if (strstr (dir_name, shadow_dir)) {
  1926. g_free (shadow_dir);
  1927. g_free (dir_name);
  1928. return (char *) filename;
  1929. }
  1930. g_free (shadow_dir);
  1931. g_free (dir_name);
  1932. shadow = get_shadow_assembly_location (filename, error);
  1933. if (!is_ok (error)) {
  1934. mono_error_cleanup (error);
  1935. mono_error_set_execution_engine (oerror, "Failed to create shadow copy (invalid characters in file name).");
  1936. return NULL;
  1937. }
  1938. if (g_ensure_directory_exists (shadow) == FALSE) {
  1939. g_free (shadow);
  1940. mono_error_set_execution_engine (oerror, "Failed to create shadow copy (ensure directory exists).");
  1941. return NULL;
  1942. }
  1943. if (!private_file_needs_copying (filename, &src_sbuf, shadow))
  1944. return (char*) shadow;
  1945. orig = g_utf8_to_utf16 (filename, strlen (filename), NULL, NULL, NULL);
  1946. dest = g_utf8_to_utf16 (shadow, strlen (shadow), NULL, NULL, NULL);
  1947. mono_w32file_delete (dest);
  1948. /* Fix for bug #17066 - make sure we can read the file. if not then don't error but rather
  1949. * let the assembly fail to load. This ensures you can do Type.GetType("NS.T, NonExistantAssembly)
  1950. * and not have it runtime error" */
  1951. attrs = mono_w32file_get_attributes (orig);
  1952. if (attrs == INVALID_FILE_ATTRIBUTES) {
  1953. g_free (shadow);
  1954. return (char *)filename;
  1955. }
  1956. copy_result = mono_w32file_copy (orig, dest, TRUE, &copy_error);
  1957. /* Fix for bug #556884 - make sure the files have the correct mode so that they can be
  1958. * overwritten when updated in their original locations. */
  1959. if (copy_result)
  1960. copy_result = mono_w32file_set_attributes (dest, FILE_ATTRIBUTE_NORMAL);
  1961. g_free (dest);
  1962. g_free (orig);
  1963. if (copy_result == FALSE) {
  1964. g_free (shadow);
  1965. /* Fix for bug #17251 - if file not found try finding assembly by other means (it is not fatal error) */
  1966. if (mono_w32error_get_last() == ERROR_FILE_NOT_FOUND || mono_w32error_get_last() == ERROR_PATH_NOT_FOUND)
  1967. return NULL; /* file not found, shadow copy failed */
  1968. mono_error_set_execution_engine (oerror, "Failed to create shadow copy (mono_w32file_copy).");
  1969. return NULL;
  1970. }
  1971. /* attempt to copy .mdb, .pdb and .config if they exist */
  1972. filename_len = strlen (filename);
  1973. shadow_len = strlen (shadow);
  1974. copy_result = shadow_copy_sibling (filename, filename_len, ".mdb", SHADOW_COPY_SIBLING_EXT_APPEND, shadow, shadow_len);
  1975. if (copy_result)
  1976. copy_result = shadow_copy_sibling (filename, filename_len, ".pdb", SHADOW_COPY_SIBLING_EXT_REPLACE, shadow, shadow_len);
  1977. if (copy_result)
  1978. copy_result = shadow_copy_sibling (filename, filename_len, ".config", SHADOW_COPY_SIBLING_EXT_APPEND, shadow, shadow_len);
  1979. if (!copy_result) {
  1980. g_free (shadow);
  1981. mono_error_set_execution_engine (oerror, "Failed to create shadow copy of sibling data (mono_w32file_copy).");
  1982. return NULL;
  1983. }
  1984. /* Create a .ini file containing the original assembly location */
  1985. if (!shadow_copy_create_ini (shadow, filename)) {
  1986. g_free (shadow);
  1987. mono_error_set_execution_engine (oerror, "Failed to create shadow copy .ini file.");
  1988. return NULL;
  1989. }
  1990. utbuf.actime = src_sbuf.st_atime;
  1991. utbuf.modtime = src_sbuf.st_mtime;
  1992. utime (shadow, &utbuf);
  1993. return shadow;
  1994. }
  1995. #endif /* DISABLE_SHADOW_COPY */
  1996. /**
  1997. * mono_domain_from_appdomain:
  1998. */
  1999. MonoDomain *
  2000. mono_domain_from_appdomain (MonoAppDomain *appdomain_raw)
  2001. {
  2002. HANDLE_FUNCTION_ENTER ();
  2003. MonoDomain *result;
  2004. MONO_ENTER_GC_UNSAFE;
  2005. MONO_HANDLE_DCL (MonoAppDomain, appdomain);
  2006. result = mono_domain_from_appdomain_handle (appdomain);
  2007. MONO_EXIT_GC_UNSAFE;
  2008. HANDLE_FUNCTION_RETURN_VAL (result);
  2009. }
  2010. MonoDomain *
  2011. mono_domain_from_appdomain_handle (MonoAppDomainHandle appdomain)
  2012. {
  2013. #ifndef ENABLE_NETCORE
  2014. HANDLE_FUNCTION_ENTER ();
  2015. MonoDomain *dom = NULL;
  2016. if (MONO_HANDLE_IS_NULL (appdomain))
  2017. goto leave;
  2018. if (mono_class_is_transparent_proxy (mono_handle_class (appdomain))) {
  2019. MonoTransparentProxyHandle tp = MONO_HANDLE_CAST (MonoTransparentProxy, appdomain);
  2020. MonoRealProxyHandle rp = MONO_HANDLE_NEW_GET (MonoRealProxy, tp, rp);
  2021. dom = mono_domain_get_by_id (MONO_HANDLE_GETVAL (rp, target_domain_id));
  2022. } else
  2023. dom = MONO_HANDLE_GETVAL (appdomain, data);
  2024. leave:
  2025. HANDLE_FUNCTION_RETURN_VAL (dom);
  2026. #else
  2027. return mono_get_root_domain ();
  2028. #endif
  2029. }
  2030. static gboolean
  2031. try_load_from (MonoAssembly **assembly,
  2032. const gchar *path1, const gchar *path2,
  2033. const gchar *path3, const gchar *path4,
  2034. const MonoAssemblyOpenRequest *req)
  2035. {
  2036. gchar *fullpath;
  2037. gboolean found = FALSE;
  2038. *assembly = NULL;
  2039. fullpath = g_build_filename (path1, path2, path3, path4, (const char*)NULL);
  2040. if (IS_PORTABILITY_SET) {
  2041. gchar *new_fullpath = mono_portability_find_file (fullpath, TRUE);
  2042. if (new_fullpath) {
  2043. g_free (fullpath);
  2044. fullpath = new_fullpath;
  2045. found = TRUE;
  2046. }
  2047. } else
  2048. found = g_file_test (fullpath, G_FILE_TEST_IS_REGULAR);
  2049. if (found) {
  2050. *assembly = mono_assembly_request_open (fullpath, req, NULL);
  2051. }
  2052. g_free (fullpath);
  2053. return (*assembly != NULL);
  2054. }
  2055. static MonoAssembly *
  2056. real_load (gchar **search_path, const gchar *culture, const gchar *name, const MonoAssemblyOpenRequest *req)
  2057. {
  2058. MonoAssembly *result = NULL;
  2059. gchar **path;
  2060. gchar *filename;
  2061. const gchar *local_culture;
  2062. gint len;
  2063. if (!culture || *culture == '\0') {
  2064. local_culture = "";
  2065. } else {
  2066. local_culture = culture;
  2067. }
  2068. filename = g_strconcat (name, ".dll", (const char*)NULL);
  2069. len = strlen (filename);
  2070. for (path = search_path; *path; path++) {
  2071. if (**path == '\0') {
  2072. continue; /* Ignore empty ApplicationBase */
  2073. }
  2074. /* See test cases in bug #58992 and bug #57710 */
  2075. /* 1st try: [culture]/[name].dll (culture may be empty) */
  2076. strcpy (filename + len - 4, ".dll");
  2077. if (try_load_from (&result, *path, local_culture, "", filename, req))
  2078. break;
  2079. /* 2nd try: [culture]/[name].exe (culture may be empty) */
  2080. strcpy (filename + len - 4, ".exe");
  2081. if (try_load_from (&result, *path, local_culture, "", filename, req))
  2082. break;
  2083. /* 3rd try: [culture]/[name]/[name].dll (culture may be empty) */
  2084. strcpy (filename + len - 4, ".dll");
  2085. if (try_load_from (&result, *path, local_culture, name, filename, req))
  2086. break;
  2087. /* 4th try: [culture]/[name]/[name].exe (culture may be empty) */
  2088. strcpy (filename + len - 4, ".exe");
  2089. if (try_load_from (&result, *path, local_culture, name, filename, req))
  2090. break;
  2091. }
  2092. g_free (filename);
  2093. return result;
  2094. }
  2095. #ifdef ENABLE_NETCORE
  2096. static char *
  2097. get_app_context_base_directory (MonoError *error)
  2098. {
  2099. MONO_STATIC_POINTER_INIT (MonoMethod, get_basedir)
  2100. ERROR_DECL (local_error);
  2101. MonoClass *app_context = mono_class_get_app_context_class ();
  2102. g_assert (app_context);
  2103. get_basedir = mono_class_get_method_from_name_checked (app_context, "get_BaseDirectory", -1, 0, local_error);
  2104. mono_error_assert_ok (local_error);
  2105. MONO_STATIC_POINTER_INIT_END (MonoMethod, get_basedir)
  2106. HANDLE_FUNCTION_ENTER ();
  2107. MonoStringHandle result = MONO_HANDLE_CAST (MonoString, mono_runtime_try_invoke_handle (get_basedir, NULL_HANDLE, NULL, error));
  2108. char *base_dir = mono_string_handle_to_utf8 (result, error);
  2109. HANDLE_FUNCTION_RETURN_VAL (base_dir);
  2110. }
  2111. #endif
  2112. /*
  2113. * Try loading the assembly from ApplicationBase and PrivateBinPath
  2114. * and then from assemblies_path if any.
  2115. * LOCKING: This is called from the assembly loading code, which means the caller
  2116. * might hold the loader lock. Thus, this function must not acquire the domain lock.
  2117. */
  2118. static MonoAssembly *
  2119. mono_domain_assembly_preload (MonoAssemblyLoadContext *alc,
  2120. MonoAssemblyName *aname,
  2121. gchar **assemblies_path,
  2122. gboolean refonly,
  2123. gpointer user_data,
  2124. MonoError *error)
  2125. {
  2126. MonoDomain *domain = mono_alc_domain (alc);
  2127. MonoAssembly *result = NULL;
  2128. #ifdef ENABLE_NETCORE
  2129. g_assert (alc);
  2130. g_assert (domain == mono_domain_get ());
  2131. #endif
  2132. #ifndef ENABLE_NETCORE
  2133. set_domain_search_path (domain);
  2134. #endif
  2135. MonoAssemblyCandidatePredicate predicate = NULL;
  2136. void* predicate_ud = NULL;
  2137. if (mono_loader_get_strict_assembly_name_check ()) {
  2138. predicate = &mono_assembly_candidate_predicate_sn_same_name;
  2139. predicate_ud = aname;
  2140. }
  2141. MonoAssemblyOpenRequest req;
  2142. mono_assembly_request_prepare_open (&req, refonly ? MONO_ASMCTX_REFONLY : MONO_ASMCTX_DEFAULT, alc);
  2143. req.request.predicate = predicate;
  2144. req.request.predicate_ud = predicate_ud;
  2145. #ifdef ENABLE_NETCORE
  2146. if (!mono_runtime_get_no_exec ()) {
  2147. char *search_path [2];
  2148. search_path [1] = NULL;
  2149. char *base_dir = get_app_context_base_directory (error);
  2150. search_path [0] = base_dir;
  2151. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Domain (%p) ApplicationBase is %s", domain, base_dir);
  2152. result = real_load (search_path, aname->culture, aname->name, &req);
  2153. g_free (base_dir);
  2154. }
  2155. #else
  2156. if (domain->search_path && domain->search_path [0] != NULL) {
  2157. if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY)) {
  2158. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Domain %s search path is:", domain->friendly_name);
  2159. for (int i = 0; domain->search_path [i]; i++) {
  2160. const char *p = domain->search_path[i];
  2161. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "\tpath[%d] = '%s'", i, p);
  2162. }
  2163. mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "End of domain %s search path.", domain->friendly_name);
  2164. }
  2165. result = real_load (domain->search_path, aname->culture, aname->name, &req);
  2166. }
  2167. #endif
  2168. if (result == NULL && assemblies_path && assemblies_path [0] != NULL) {
  2169. result = real_load (assemblies_path, aname->culture, aname->name, &req);
  2170. }
  2171. return result;
  2172. }
  2173. /*
  2174. * Check whenever a given assembly was already loaded in the current appdomain.
  2175. */
  2176. static MonoAssembly *
  2177. mono_domain_assembly_search (MonoAssemblyLoadContext *alc, MonoAssembly *requesting,
  2178. MonoAssemblyName *aname,
  2179. gboolean refonly,
  2180. gboolean postload,
  2181. gpointer user_data,
  2182. MonoError *error)
  2183. {
  2184. g_assert (aname != NULL);
  2185. GSList *tmp;
  2186. MonoAssembly *ass;
  2187. #ifdef ENABLE_NETCORE
  2188. const MonoAssemblyNameEqFlags eq_flags = MONO_ANAME_EQ_IGNORE_PUBKEY | MONO_ANAME_EQ_IGNORE_VERSION | MONO_ANAME_EQ_IGNORE_CASE;
  2189. mono_alc_assemblies_lock (alc);
  2190. for (tmp = alc->loaded_assemblies; tmp; tmp = tmp->next) {
  2191. ass = (MonoAssembly *)tmp->data;
  2192. g_assert (ass != NULL);
  2193. // FIXME: Can dynamic assemblies match here for netcore?
  2194. if (assembly_is_dynamic (ass) || !mono_assembly_names_equal_flags (aname, &ass->aname, eq_flags))
  2195. continue;
  2196. mono_alc_assemblies_unlock (alc);
  2197. return ass;
  2198. }
  2199. mono_alc_assemblies_unlock (alc);
  2200. #else
  2201. MonoDomain *domain = mono_alc_domain (alc);
  2202. const gboolean strong_name = aname->public_key_token[0] != 0;
  2203. /* If it's not a strong name, any version that has the right simple
  2204. * name is good enough to satisfy the request. .NET Framework also
  2205. * ignores case differences in this case. */
  2206. const MonoAssemblyNameEqFlags eq_flags = (MonoAssemblyNameEqFlags)((strong_name && !ignore_version_and_key_when_finding_assemblies_already_loaded) ? MONO_ANAME_EQ_IGNORE_CASE :
  2207. (MONO_ANAME_EQ_IGNORE_PUBKEY | MONO_ANAME_EQ_IGNORE_VERSION | MONO_ANAME_EQ_IGNORE_CASE));
  2208. mono_domain_assemblies_lock (domain);
  2209. for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
  2210. ass = (MonoAssembly *)tmp->data;
  2211. g_assert (ass != NULL);
  2212. /* Dynamic assemblies can't match here in MS.NET */
  2213. gboolean ass_ref_only = mono_asmctx_get_kind (&ass->context) == MONO_ASMCTX_REFONLY;
  2214. if (assembly_is_dynamic (ass) || refonly != ass_ref_only || !mono_assembly_names_equal_flags (aname, &ass->aname, eq_flags))
  2215. continue;
  2216. mono_domain_assemblies_unlock (domain);
  2217. return ass;
  2218. }
  2219. mono_domain_assemblies_unlock (domain);
  2220. #endif
  2221. return NULL;
  2222. }
  2223. #if ENABLE_NETCORE
  2224. MonoReflectionAssemblyHandle
  2225. ves_icall_System_Reflection_Assembly_InternalLoad (MonoStringHandle name_handle, MonoStackCrawlMark *stack_mark, gpointer load_Context, MonoError *error)
  2226. {
  2227. error_init (error);
  2228. MonoAssembly *ass = NULL;
  2229. MonoAssemblyName aname;
  2230. MonoAssemblyByNameRequest req;
  2231. MonoAssemblyContextKind asmctx;
  2232. MonoImageOpenStatus status = MONO_IMAGE_OK;
  2233. gboolean parsed;
  2234. char *name;
  2235. MonoAssembly *requesting_assembly = mono_runtime_get_caller_from_stack_mark (stack_mark);
  2236. MonoAssemblyLoadContext *alc = (MonoAssemblyLoadContext *)load_Context;
  2237. if (!alc)
  2238. alc = mono_assembly_get_alc (requesting_assembly);
  2239. if (!alc)
  2240. g_assert_not_reached ();
  2241. MonoDomain *domain = mono_alc_domain (alc);
  2242. g_assert (alc);
  2243. asmctx = MONO_ASMCTX_DEFAULT;
  2244. mono_assembly_request_prepare_byname (&req, asmctx, alc);
  2245. req.basedir = NULL;
  2246. /* Everything currently goes through this function, and the postload hook (aka the AppDomain.AssemblyResolve event)
  2247. * is triggered under some scenarios. It's not completely obvious to me in what situations (if any) this should be disabled,
  2248. * other than for corlib satellite assemblies (which I've dealt with further down the call stack).
  2249. */
  2250. //req.no_postload_search = TRUE;
  2251. req.requesting_assembly = requesting_assembly;
  2252. name = mono_string_handle_to_utf8 (name_handle, error);
  2253. goto_if_nok (error, fail);
  2254. parsed = mono_assembly_name_parse (name, &aname);
  2255. g_free (name);
  2256. if (!parsed)
  2257. goto fail;
  2258. MonoAssemblyCandidatePredicate predicate;
  2259. void* predicate_ud;
  2260. predicate = NULL;
  2261. predicate_ud = NULL;
  2262. if (mono_loader_get_strict_assembly_name_check ()) {
  2263. predicate = &mono_assembly_candidate_predicate_sn_same_name;
  2264. predicate_ud = &aname;
  2265. }
  2266. req.request.predicate = predicate;
  2267. req.request.predicate_ud = predicate_ud;
  2268. ass = mono_assembly_request_byname (&aname, &req, &status);
  2269. if (!ass)
  2270. goto fail;
  2271. MonoReflectionAssemblyHandle refass;
  2272. refass = mono_assembly_get_object_handle (domain, ass, error);
  2273. goto_if_nok (error, fail);
  2274. return refass;
  2275. fail:
  2276. return MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
  2277. }
  2278. #endif
  2279. #ifndef ENABLE_NETCORE
  2280. MonoReflectionAssemblyHandle
  2281. ves_icall_System_Reflection_Assembly_LoadFrom (MonoStringHandle fname, MonoBoolean refOnly, MonoStackCrawlMark *stack_mark, MonoError *error)
  2282. {
  2283. error_init (error);
  2284. MonoDomain *domain = mono_domain_get ();
  2285. char *name, *filename;
  2286. MonoImageOpenStatus status = MONO_IMAGE_OK;
  2287. MonoReflectionAssemblyHandle result = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
  2288. name = NULL;
  2289. if (MONO_HANDLE_IS_NULL (fname)) {
  2290. mono_error_set_argument_null (error, "assemblyFile", "");
  2291. goto leave;
  2292. }
  2293. name = filename = mono_string_handle_to_utf8 (fname, error);
  2294. goto_if_nok (error, leave);
  2295. MonoAssembly *requesting_assembly;
  2296. requesting_assembly = NULL;
  2297. if (!refOnly)
  2298. requesting_assembly = mono_runtime_get_caller_from_stack_mark (stack_mark);
  2299. MonoAssembly *ass;
  2300. MonoAssemblyOpenRequest req;
  2301. mono_assembly_request_prepare_open (&req, refOnly ? MONO_ASMCTX_REFONLY : MONO_ASMCTX_LOADFROM, mono_domain_default_alc (domain));
  2302. req.requesting_assembly = requesting_assembly;
  2303. ass = mono_assembly_request_open (filename, &req, &status);
  2304. if (!ass) {
  2305. if (status == MONO_IMAGE_IMAGE_INVALID)
  2306. mono_error_set_bad_image_by_name (error, name, "Invalid Image: %s", name);
  2307. else
  2308. mono_error_set_simple_file_not_found (error, name, refOnly);
  2309. goto leave;
  2310. }
  2311. result = mono_assembly_get_object_handle (domain, ass, error);
  2312. leave:
  2313. g_free (name);
  2314. return result;
  2315. }
  2316. #endif
  2317. static
  2318. MonoAssembly *
  2319. mono_alc_load_file (MonoAssemblyLoadContext *alc, MonoStringHandle fname, MonoAssembly *executing_assembly, MonoAssemblyContextKind asmctx, MonoError *error)
  2320. {
  2321. MonoAssembly *ass = NULL;
  2322. HANDLE_FUNCTION_ENTER ();
  2323. char *filename = NULL;
  2324. if (MONO_HANDLE_IS_NULL (fname)) {
  2325. mono_error_set_argument_null (error, "assemblyFile", "");
  2326. goto leave;
  2327. }
  2328. filename = mono_string_handle_to_utf8 (fname, error);
  2329. goto_if_nok (error, leave);
  2330. if (!g_path_is_absolute (filename)) {
  2331. mono_error_set_argument (error, "assemblyFile", "Absolute path information is required.");
  2332. goto leave;
  2333. }
  2334. MonoImageOpenStatus status;
  2335. MonoAssemblyOpenRequest req;
  2336. mono_assembly_request_prepare_open (&req, asmctx, alc);
  2337. req.requesting_assembly = executing_assembly;
  2338. ass = mono_assembly_request_open (filename, &req, &status);
  2339. if (!ass) {
  2340. if (status == MONO_IMAGE_IMAGE_INVALID)
  2341. mono_error_set_bad_image_by_name (error, filename, "Invalid Image: %s", filename);
  2342. else
  2343. mono_error_set_simple_file_not_found (error, filename, asmctx == MONO_ASMCTX_REFONLY);
  2344. }
  2345. leave:
  2346. g_free (filename);
  2347. HANDLE_FUNCTION_RETURN_VAL (ass);
  2348. }
  2349. #ifndef ENABLE_NETCORE
  2350. MonoReflectionAssemblyHandle
  2351. ves_icall_System_Reflection_Assembly_LoadFile_internal (MonoStringHandle fname, MonoStackCrawlMark *stack_mark, MonoError *error)
  2352. {
  2353. MonoDomain *domain = mono_domain_get ();
  2354. MonoReflectionAssemblyHandle result = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
  2355. MonoAssembly *executing_assembly;
  2356. executing_assembly = mono_runtime_get_caller_from_stack_mark (stack_mark);
  2357. MonoAssembly *ass = mono_alc_load_file (mono_domain_default_alc (domain), fname, executing_assembly, MONO_ASMCTX_INDIVIDUAL, error);
  2358. goto_if_nok (error, leave);
  2359. result = mono_assembly_get_object_handle (domain, ass, error);
  2360. leave:
  2361. return result;
  2362. }
  2363. #else
  2364. MonoReflectionAssemblyHandle
  2365. ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalLoadFile (gpointer alc_ptr, MonoStringHandle fname, MonoStackCrawlMark *stack_mark, MonoError *error)
  2366. {
  2367. MonoReflectionAssemblyHandle result = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
  2368. MonoAssemblyLoadContext *alc = (MonoAssemblyLoadContext *)alc_ptr;
  2369. MonoDomain *domain = mono_alc_domain (alc);
  2370. MonoAssembly *executing_assembly;
  2371. executing_assembly = mono_runtime_get_caller_from_stack_mark (stack_mark);
  2372. MonoAssembly *ass = mono_alc_load_file (alc, fname, executing_assembly, mono_alc_is_default (alc) ? MONO_ASMCTX_LOADFROM : MONO_ASMCTX_INDIVIDUAL, error);
  2373. goto_if_nok (error, leave);
  2374. result = mono_assembly_get_object_handle (domain, ass, error);
  2375. leave:
  2376. return result;
  2377. }
  2378. #endif
  2379. static MonoAssembly*
  2380. mono_alc_load_raw_bytes (MonoAssemblyLoadContext *alc, guint8 *raw_assembly, guint32 raw_assembly_len, guint8 *raw_symbol_data, guint32 raw_symbol_len, gboolean refonly, MonoError *error);
  2381. #ifdef ENABLE_NETCORE
  2382. MonoReflectionAssemblyHandle
  2383. ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalLoadFromStream (gpointer native_alc, gpointer raw_assembly_ptr, gint32 raw_assembly_len, gpointer raw_symbols_ptr, gint32 raw_symbols_len, MonoError *error)
  2384. {
  2385. MonoAssemblyLoadContext *alc = (MonoAssemblyLoadContext *)native_alc;
  2386. MonoDomain *domain = mono_alc_domain (alc);
  2387. MonoReflectionAssemblyHandle result = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
  2388. MonoAssembly *assm = NULL;
  2389. assm = mono_alc_load_raw_bytes (alc, (guint8 *)raw_assembly_ptr, raw_assembly_len, (guint8 *)raw_symbols_ptr, raw_symbols_len, FALSE, error);
  2390. goto_if_nok (error, leave);
  2391. result = mono_assembly_get_object_handle (domain, assm, error);
  2392. leave:
  2393. return result;
  2394. }
  2395. #else
  2396. MonoReflectionAssemblyHandle
  2397. ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomainHandle ad,
  2398. MonoArrayHandle raw_assembly,
  2399. MonoArrayHandle raw_symbol_store, MonoObjectHandle evidence,
  2400. MonoBoolean refonly,
  2401. MonoError *error)
  2402. {
  2403. MonoAssembly *ass;
  2404. MonoReflectionAssemblyHandle refass = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
  2405. MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data);
  2406. MonoAssemblyLoadContext *alc = mono_domain_default_alc (domain);
  2407. guint8 *raw_assembly_ptr = (guint8 *)mono_array_handle_addr (raw_assembly, sizeof (guint8), 0);
  2408. guint32 raw_assembly_len = mono_array_handle_length (raw_assembly);
  2409. guint8 *raw_symbols_ptr = NULL;
  2410. guint32 raw_symbols_len = 0;
  2411. if (!MONO_HANDLE_IS_NULL (raw_symbol_store)) {
  2412. raw_symbols_ptr = (guint8 *)mono_array_handle_addr (raw_symbol_store, sizeof (guint8), 0);
  2413. raw_symbols_len = mono_array_handle_length (raw_symbol_store);
  2414. }
  2415. ass = mono_alc_load_raw_bytes (alc, raw_assembly_ptr, raw_assembly_len, raw_symbols_ptr, raw_symbols_len, refonly, error);
  2416. goto_if_nok (error, leave);
  2417. refass = mono_assembly_get_object_handle (domain, ass, error);
  2418. if (!MONO_HANDLE_IS_NULL (refass))
  2419. MONO_HANDLE_SET (refass, evidence, evidence);
  2420. leave:
  2421. return refass;
  2422. }
  2423. #endif /* ENABLE_NETCORE */
  2424. static MonoAssembly*
  2425. mono_alc_load_raw_bytes (MonoAssemblyLoadContext *alc, guint8 *assembly_data, guint32 raw_assembly_len, guint8 *raw_symbol_data, guint32 raw_symbol_len, gboolean refonly, MonoError *error)
  2426. {
  2427. MonoAssembly *ass = NULL;
  2428. MonoImageOpenStatus status;
  2429. MonoImage *image = mono_image_open_from_data_internal (alc, (char*)assembly_data, raw_assembly_len, TRUE, NULL, refonly, FALSE, NULL, NULL);
  2430. if (!image) {
  2431. mono_error_set_bad_image_by_name (error, "In memory assembly", "0x%p", assembly_data);
  2432. return ass;
  2433. }
  2434. if (raw_symbol_data)
  2435. mono_debug_open_image_from_memory (image, raw_symbol_data, raw_symbol_len);
  2436. #ifndef ENABLE_NETCORE
  2437. MonoAssembly* redirected_asm = NULL;
  2438. MonoImageOpenStatus new_status = MONO_IMAGE_OK;
  2439. // http://blogs.microsoft.co.il/sasha/2010/06/09/assemblyreflectiononlyload-ignores-assembly-binding-redirects/
  2440. if (!refonly && (redirected_asm = mono_assembly_binding_applies_to_image (alc, image, &new_status))) {
  2441. mono_image_close (image);
  2442. image = redirected_asm->image;
  2443. mono_image_addref (image); /* so that mono_image close, below, has something to do */
  2444. } else if (new_status != MONO_IMAGE_OK) {
  2445. mono_image_close (image);
  2446. mono_error_set_bad_image_by_name (error, "In Memory assembly", "0x%p was assembly binding redirected to another assembly that failed to load", assembly_data);
  2447. return ass;
  2448. }
  2449. #endif
  2450. MonoAssemblyLoadRequest req;
  2451. mono_assembly_request_prepare_load (&req, refonly? MONO_ASMCTX_REFONLY : MONO_ASMCTX_INDIVIDUAL, alc);
  2452. ass = mono_assembly_request_load_from (image, "", &req, &status);
  2453. if (!ass) {
  2454. mono_image_close (image);
  2455. mono_error_set_bad_image_by_name (error, "In Memory assembly", "0x%p", assembly_data);
  2456. return ass;
  2457. }
  2458. /* Clear the reference added by mono_image_open_from_data_internal above */
  2459. mono_image_close (image);
  2460. return ass;
  2461. }
  2462. #ifndef ENABLE_NETCORE
  2463. MonoReflectionAssemblyHandle
  2464. ves_icall_System_AppDomain_LoadAssembly (MonoAppDomainHandle ad, MonoStringHandle assRef, MonoObjectHandle evidence, MonoBoolean refOnly, MonoStackCrawlMark *stack_mark, MonoError *error)
  2465. {
  2466. MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data);
  2467. MonoImageOpenStatus status = MONO_IMAGE_OK;
  2468. MonoAssembly *ass;
  2469. MonoAssemblyName aname;
  2470. gchar *name = NULL;
  2471. gboolean parsed;
  2472. g_assert (!MONO_HANDLE_IS_NULL (assRef));
  2473. name = mono_string_handle_to_utf8 (assRef, error);
  2474. goto_if_nok (error, fail);
  2475. parsed = mono_assembly_name_parse (name, &aname);
  2476. g_free (name);
  2477. if (!parsed) {
  2478. MonoReflectionAssemblyHandle refass = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
  2479. /* This is a parse error... */
  2480. if (!refOnly) {
  2481. MonoAssembly *assm = mono_try_assembly_resolve_handle (mono_domain_default_alc (domain), assRef, NULL, refOnly, error);
  2482. goto_if_nok (error, fail);
  2483. if (assm) {
  2484. refass = mono_assembly_get_object_handle (domain, assm, error);
  2485. goto_if_nok (error, fail);
  2486. }
  2487. }
  2488. return refass;
  2489. }
  2490. MonoAssemblyContextKind asmctx;
  2491. asmctx = refOnly ? MONO_ASMCTX_REFONLY : MONO_ASMCTX_DEFAULT;
  2492. const char *basedir;
  2493. basedir = NULL;
  2494. if (!refOnly) {
  2495. /* Determine if the current assembly is in LoadFrom context.
  2496. * If it is, we must include the executing assembly's basedir
  2497. * when probing for the given assembly name, and also load the
  2498. * requested assembly in LoadFrom context.
  2499. */
  2500. MonoAssembly *executing_assembly = mono_runtime_get_caller_from_stack_mark (stack_mark);
  2501. if (executing_assembly && mono_asmctx_get_kind (&executing_assembly->context) == MONO_ASMCTX_LOADFROM) {
  2502. asmctx = MONO_ASMCTX_LOADFROM;
  2503. basedir = executing_assembly->basedir;
  2504. }
  2505. }
  2506. MonoAssemblyByNameRequest req;
  2507. mono_assembly_request_prepare_byname (&req, asmctx, mono_domain_default_alc (domain));
  2508. req.basedir = basedir;
  2509. req.no_postload_search = TRUE;
  2510. ass = mono_assembly_request_byname (&aname, &req, &status);
  2511. mono_assembly_name_free_internal (&aname);
  2512. if (!ass) {
  2513. /* MS.NET doesn't seem to call the assembly resolve handler for refonly assemblies */
  2514. if (!refOnly) {
  2515. ass = mono_try_assembly_resolve_handle (mono_domain_default_alc (domain), assRef, NULL, refOnly, error);
  2516. goto_if_nok (error, fail);
  2517. }
  2518. if (!ass)
  2519. goto fail;
  2520. }
  2521. g_assert (ass);
  2522. MonoReflectionAssemblyHandle refass;
  2523. refass = mono_assembly_get_object_handle (domain, ass, error);
  2524. goto_if_nok (error, fail);
  2525. MONO_HANDLE_SET (refass, evidence, evidence);
  2526. return refass;
  2527. fail:
  2528. return MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
  2529. }
  2530. void
  2531. ves_icall_System_AppDomain_InternalUnload (gint32 domain_id, MonoError *error)
  2532. {
  2533. MonoDomain * domain = mono_domain_get_by_id (domain_id);
  2534. if (NULL == domain) {
  2535. mono_error_set_execution_engine (error, "Failed to unload domain, domain id not found");
  2536. return;
  2537. }
  2538. if (domain == mono_get_root_domain ()) {
  2539. mono_error_set_generic_error (error, "System", "CannotUnloadAppDomainException", "The default appdomain can not be unloaded.");
  2540. return;
  2541. }
  2542. /*
  2543. * Unloading seems to cause problems when running NUnit/NAnt, hence
  2544. * this workaround.
  2545. */
  2546. if (g_hasenv ("MONO_NO_UNLOAD"))
  2547. return;
  2548. MonoException *exc = NULL;
  2549. mono_domain_try_unload (domain, (MonoObject**)&exc, NULL);
  2550. if (exc)
  2551. mono_error_set_exception_instance (error, exc);
  2552. }
  2553. MonoBoolean
  2554. ves_icall_System_AppDomain_InternalIsFinalizingForUnload (gint32 domain_id, MonoError *error)
  2555. {
  2556. MonoDomain *domain = mono_domain_get_by_id (domain_id);
  2557. if (!domain)
  2558. return TRUE;
  2559. return mono_domain_is_unloading (domain);
  2560. }
  2561. void
  2562. ves_icall_System_AppDomain_DoUnhandledException (MonoAppDomainHandle ad, MonoExceptionHandle exc, MonoError *error)
  2563. {
  2564. mono_unhandled_exception_checked (MONO_HANDLE_CAST (MonoObject, exc), error);
  2565. mono_error_assert_ok (error);
  2566. }
  2567. gint32
  2568. ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomainHandle ad,
  2569. MonoReflectionAssemblyHandle refass, MonoArrayHandle args,
  2570. MonoError *error)
  2571. {
  2572. MonoImage *image;
  2573. MonoMethod *method;
  2574. g_assert (!MONO_HANDLE_IS_NULL (refass));
  2575. MonoAssembly *assembly = MONO_HANDLE_GETVAL (refass, assembly);
  2576. image = assembly->image;
  2577. g_assert (image);
  2578. method = mono_get_method_checked (image, mono_image_get_entry_point (image), NULL, NULL, error);
  2579. if (!method)
  2580. g_error ("No entry point method found in %s due to %s", image->name, mono_error_get_message (error));
  2581. if (MONO_HANDLE_IS_NULL (args)) {
  2582. MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data);
  2583. MONO_HANDLE_ASSIGN (args , mono_array_new_handle (domain, mono_defaults.string_class, 0, error));
  2584. mono_error_assert_ok (error);
  2585. }
  2586. int res = mono_runtime_exec_main_checked (method, MONO_HANDLE_RAW (args), error);
  2587. return res;
  2588. }
  2589. MonoAppDomainHandle
  2590. ves_icall_System_AppDomain_InternalSetDomain (MonoAppDomainHandle ad, MonoError* error)
  2591. {
  2592. error_init (error);
  2593. MonoDomain *old_domain = mono_domain_get ();
  2594. if (!mono_domain_set_fast (MONO_HANDLE_GETVAL (ad, data), FALSE)) {
  2595. mono_error_set_appdomain_unloaded (error);
  2596. return MONO_HANDLE_CAST (MonoAppDomain, NULL_HANDLE);
  2597. }
  2598. return MONO_HANDLE_NEW (MonoAppDomain, old_domain->domain);
  2599. }
  2600. MonoAppDomainHandle
  2601. ves_icall_System_AppDomain_InternalSetDomainByID (gint32 domainid, MonoError *error)
  2602. {
  2603. MonoDomain *current_domain = mono_domain_get ();
  2604. MonoDomain *domain = mono_domain_get_by_id (domainid);
  2605. if (!domain || !mono_domain_set_fast (domain, FALSE)) {
  2606. mono_error_set_appdomain_unloaded (error);
  2607. return MONO_HANDLE_CAST (MonoAppDomain, NULL_HANDLE);
  2608. }
  2609. return MONO_HANDLE_NEW (MonoAppDomain, current_domain->domain);
  2610. }
  2611. void
  2612. ves_icall_System_AppDomain_InternalPushDomainRef (MonoAppDomainHandle ad, MonoError *error)
  2613. {
  2614. error_init (error);
  2615. mono_thread_push_appdomain_ref (MONO_HANDLE_GETVAL (ad, data));
  2616. }
  2617. void
  2618. ves_icall_System_AppDomain_InternalPushDomainRefByID (gint32 domain_id, MonoError *error)
  2619. {
  2620. error_init (error);
  2621. MonoDomain *domain = mono_domain_get_by_id (domain_id);
  2622. if (!domain) {
  2623. /*
  2624. * Raise an exception to prevent the managed code from executing a pop
  2625. * later.
  2626. */
  2627. mono_error_set_appdomain_unloaded (error);
  2628. return;
  2629. }
  2630. mono_thread_push_appdomain_ref (domain);
  2631. }
  2632. void
  2633. ves_icall_System_AppDomain_InternalPopDomainRef (MonoError *error)
  2634. {
  2635. error_init (error);
  2636. mono_thread_pop_appdomain_ref ();
  2637. }
  2638. MonoAppContextHandle
  2639. ves_icall_System_AppDomain_InternalGetContext (MonoError *error)
  2640. {
  2641. error_init (error);
  2642. return mono_context_get_handle ();
  2643. }
  2644. MonoAppContextHandle
  2645. ves_icall_System_AppDomain_InternalGetDefaultContext (MonoError *error)
  2646. {
  2647. error_init (error);
  2648. return MONO_HANDLE_NEW (MonoAppContext, mono_domain_get ()->default_context);
  2649. }
  2650. MonoAppContextHandle
  2651. ves_icall_System_AppDomain_InternalSetContext (MonoAppContextHandle mc, MonoError *error)
  2652. {
  2653. error_init (error);
  2654. MonoAppContextHandle old_context = mono_context_get_handle ();
  2655. mono_context_set_handle (mc);
  2656. return old_context;
  2657. }
  2658. MonoStringHandle
  2659. ves_icall_System_AppDomain_InternalGetProcessGuid (MonoStringHandle newguid, MonoError *error)
  2660. {
  2661. error_init (error);
  2662. MonoDomain* mono_root_domain = mono_get_root_domain ();
  2663. mono_domain_lock (mono_root_domain);
  2664. if (process_guid_set) {
  2665. mono_domain_unlock (mono_root_domain);
  2666. return mono_string_new_utf16_handle (mono_domain_get (), process_guid, sizeof(process_guid)/2, error);
  2667. }
  2668. MonoGCHandle gchandle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, newguid), TRUE);
  2669. memcpy (process_guid, mono_string_chars_internal (MONO_HANDLE_RAW (newguid)), sizeof(process_guid));
  2670. mono_gchandle_free_internal (gchandle);
  2671. process_guid_set = TRUE;
  2672. mono_domain_unlock (mono_root_domain);
  2673. return newguid;
  2674. }
  2675. #endif
  2676. /**
  2677. * mono_domain_is_unloading:
  2678. */
  2679. gboolean
  2680. mono_domain_is_unloading (MonoDomain *domain)
  2681. {
  2682. if (domain->state == MONO_APPDOMAIN_UNLOADING || domain->state == MONO_APPDOMAIN_UNLOADED)
  2683. return TRUE;
  2684. else
  2685. return FALSE;
  2686. }
  2687. #ifndef ENABLE_NETCORE
  2688. static void
  2689. clear_cached_vtable (MonoVTable *vtable)
  2690. {
  2691. MonoClass *klass = vtable->klass;
  2692. MonoDomain *domain = vtable->domain;
  2693. MonoClassRuntimeInfo *runtime_info;
  2694. void *data;
  2695. runtime_info = m_class_get_runtime_info (klass);
  2696. if (runtime_info && runtime_info->max_domain >= domain->domain_id)
  2697. runtime_info->domain_vtables [domain->domain_id] = NULL;
  2698. if (m_class_has_static_refs (klass) && (data = mono_vtable_get_static_field_data (vtable)))
  2699. mono_gc_free_fixed (data);
  2700. }
  2701. static G_GNUC_UNUSED void
  2702. zero_static_data (MonoVTable *vtable)
  2703. {
  2704. MonoClass *klass = vtable->klass;
  2705. void *data;
  2706. if (m_class_has_static_refs (klass) && (data = mono_vtable_get_static_field_data (vtable)))
  2707. mono_gc_bzero_aligned (data, mono_class_data_size (klass));
  2708. }
  2709. typedef struct unload_data {
  2710. gboolean done;
  2711. MonoDomain *domain;
  2712. char *failure_reason;
  2713. gint32 refcount;
  2714. } unload_data;
  2715. static void
  2716. unload_data_unref (unload_data *data)
  2717. {
  2718. if (!data)
  2719. return;
  2720. gint32 count;
  2721. do {
  2722. mono_atomic_load_acquire (count, gint32, &data->refcount);
  2723. g_assert (count >= 1 && count <= 2);
  2724. if (count == 1) {
  2725. g_free (data);
  2726. return;
  2727. }
  2728. } while (mono_atomic_cas_i32 (&data->refcount, count - 1, count) != count);
  2729. }
  2730. static void
  2731. deregister_reflection_info_roots_from_list (MonoImage *image)
  2732. {
  2733. GSList *list = image->reflection_info_unregister_classes;
  2734. while (list) {
  2735. MonoClass *klass = (MonoClass *)list->data;
  2736. mono_class_free_ref_info (klass);
  2737. list = list->next;
  2738. }
  2739. image->reflection_info_unregister_classes = NULL;
  2740. }
  2741. static void
  2742. deregister_reflection_info_roots (MonoDomain *domain)
  2743. {
  2744. GSList *list;
  2745. mono_domain_assemblies_lock (domain);
  2746. for (list = domain->domain_assemblies; list; list = list->next) {
  2747. MonoAssembly *assembly = (MonoAssembly *)list->data;
  2748. MonoImage *image = assembly->image;
  2749. int i;
  2750. /*
  2751. * No need to take the image lock here since dynamic images are appdomain bound and
  2752. * at this point the mutator is gone. Taking the image lock here would mean
  2753. * promoting it from a simple lock to a complex lock, which we better avoid if
  2754. * possible.
  2755. */
  2756. if (image_is_dynamic (image))
  2757. deregister_reflection_info_roots_from_list (image);
  2758. for (i = 0; i < image->module_count; ++i) {
  2759. MonoImage *module = image->modules [i];
  2760. if (module && image_is_dynamic (module))
  2761. deregister_reflection_info_roots_from_list (module);
  2762. }
  2763. }
  2764. mono_domain_assemblies_unlock (domain);
  2765. }
  2766. static gsize WINAPI
  2767. unload_thread_main (void *arg)
  2768. {
  2769. unload_data *data = (unload_data*)arg;
  2770. MonoDomain *domain = data->domain;
  2771. MonoMemoryManager *memory_manager = mono_domain_memory_manager (domain);
  2772. int i;
  2773. gsize result = 1; // failure
  2774. mono_thread_set_name_constant_ignore_error (mono_thread_internal_current (), "Domain unloader", MonoSetThreadNameFlag_Permanent);
  2775. /*
  2776. * FIXME: Abort our parent thread last, so we can return a failure
  2777. * indication if aborting times out.
  2778. */
  2779. if (!mono_threads_abort_appdomain_threads (domain, -1)) {
  2780. data->failure_reason = g_strdup_printf ("Aborting of threads in domain %s timed out.", domain->friendly_name);
  2781. goto failure;
  2782. }
  2783. if (!mono_threadpool_remove_domain_jobs (domain, -1)) {
  2784. data->failure_reason = g_strdup_printf ("Cleanup of threadpool jobs of domain %s timed out.", domain->friendly_name);
  2785. goto failure;
  2786. }
  2787. /* Finalize all finalizable objects in the doomed appdomain */
  2788. if (!mono_domain_finalize (domain, -1)) {
  2789. data->failure_reason = g_strdup_printf ("Finalization of domain %s timed out.", domain->friendly_name);
  2790. goto failure;
  2791. }
  2792. /* Clear references to our vtables in class->runtime_info.
  2793. * We also hold the loader lock because we're going to change
  2794. * class->runtime_info.
  2795. */
  2796. mono_loader_lock ();
  2797. mono_domain_lock (domain);
  2798. mono_mem_manager_lock (memory_manager);
  2799. /*
  2800. * We need to make sure that we don't have any remsets
  2801. * pointing into static data of the to-be-freed domain because
  2802. * at the next collections they would be invalid. So what we
  2803. * do is we first zero all static data and then do a minor
  2804. * collection. Because all references in the static data will
  2805. * now be null we won't do any unnecessary copies and after
  2806. * the collection there won't be any more remsets.
  2807. */
  2808. for (i = 0; i < memory_manager->class_vtable_array->len; ++i)
  2809. zero_static_data ((MonoVTable *)g_ptr_array_index (memory_manager->class_vtable_array, i));
  2810. #if !HAVE_BOEHM_GC
  2811. mono_gc_collect (0);
  2812. #endif
  2813. for (i = 0; i < memory_manager->class_vtable_array->len; ++i)
  2814. clear_cached_vtable ((MonoVTable *)g_ptr_array_index (memory_manager->class_vtable_array, i));
  2815. deregister_reflection_info_roots (domain);
  2816. mono_assembly_cleanup_domain_bindings (domain->domain_id);
  2817. mono_mem_manager_unlock (memory_manager);
  2818. mono_domain_unlock (domain);
  2819. mono_loader_unlock ();
  2820. domain->state = MONO_APPDOMAIN_UNLOADED;
  2821. /* printf ("UNLOADED %s.\n", domain->friendly_name); */
  2822. /* remove from the handle table the items related to this domain */
  2823. mono_gchandle_free_domain (domain);
  2824. mono_domain_free (domain, FALSE);
  2825. result = 0; // success
  2826. exit:
  2827. mono_atomic_store_release (&data->done, TRUE);
  2828. unload_data_unref (data);
  2829. return result;
  2830. failure:
  2831. result = 1;
  2832. goto exit;
  2833. }
  2834. /**
  2835. * mono_domain_unload:
  2836. * \param domain The domain to unload
  2837. *
  2838. * Unloads an appdomain. Follows the process outlined in the comment
  2839. * for \c mono_domain_try_unload.
  2840. */
  2841. void
  2842. mono_domain_unload (MonoDomain *domain)
  2843. {
  2844. MONO_ENTER_GC_UNSAFE;
  2845. MonoObject *exc = NULL;
  2846. mono_domain_try_unload (domain, &exc, NULL);
  2847. MONO_EXIT_GC_UNSAFE;
  2848. }
  2849. static MonoThreadInfoWaitRet
  2850. guarded_wait (MonoThreadHandle *thread_handle, guint32 timeout, gboolean alertable)
  2851. {
  2852. MonoThreadInfoWaitRet result;
  2853. MONO_ENTER_GC_SAFE;
  2854. result = mono_thread_info_wait_one_handle (thread_handle, timeout, alertable);
  2855. MONO_EXIT_GC_SAFE;
  2856. return result;
  2857. }
  2858. /**
  2859. * mono_domain_try_unload:
  2860. * \param domain The domain to unload
  2861. * \param exc Exception information
  2862. *
  2863. * Unloads an appdomain. Follows the process outlined in:
  2864. * http://blogs.gotdotnet.com/cbrumme
  2865. *
  2866. * If doing things the 'right' way is too hard or complex, we do it the
  2867. * 'simple' way, which means do everything needed to avoid crashes and
  2868. * memory leaks, but not much else.
  2869. *
  2870. * It is required to pass a valid reference to the exc argument, upon return
  2871. * from this function *exc will be set to the exception thrown, if any.
  2872. *
  2873. * If this method is not called from an icall (embedded scenario for instance),
  2874. * it must not be called with any managed frames on the stack, since the unload
  2875. * process could end up trying to abort the current thread.
  2876. */
  2877. void
  2878. mono_domain_try_unload (MonoDomain *domain, MonoObject **exc, MonoUnityExceptionFunc callback)
  2879. {
  2880. HANDLE_FUNCTION_ENTER ();
  2881. ERROR_DECL (error);
  2882. MonoThreadHandle *thread_handle = NULL;
  2883. MonoAppDomainState prev_state;
  2884. MonoMethod *method;
  2885. unload_data *thread_data = NULL;
  2886. MonoInternalThreadHandle internal;
  2887. MonoDomain *caller_domain = mono_domain_get ();
  2888. /* printf ("UNLOAD STARTING FOR %s (%p) IN THREAD 0x%x.\n", domain->friendly_name, domain, mono_native_thread_id_get ()); */
  2889. /* Atomically change our state to UNLOADING */
  2890. prev_state = (MonoAppDomainState)mono_atomic_cas_i32 ((gint32*)&domain->state,
  2891. MONO_APPDOMAIN_UNLOADING_START,
  2892. MONO_APPDOMAIN_CREATED);
  2893. if (prev_state != MONO_APPDOMAIN_CREATED) {
  2894. switch (prev_state) {
  2895. case MONO_APPDOMAIN_UNLOADING_START:
  2896. case MONO_APPDOMAIN_UNLOADING:
  2897. *exc = (MonoObject *) mono_get_exception_cannot_unload_appdomain ("Appdomain is already being unloaded.");
  2898. goto exit;
  2899. case MONO_APPDOMAIN_UNLOADED:
  2900. *exc = (MonoObject *) mono_get_exception_cannot_unload_appdomain ("Appdomain is already unloaded.");
  2901. goto exit;
  2902. default:
  2903. g_warning ("Invalid appdomain state %d", prev_state);
  2904. g_assert_not_reached ();
  2905. }
  2906. }
  2907. mono_domain_set_fast (domain, FALSE);
  2908. /* Notify OnDomainUnload listeners */
  2909. method = mono_class_get_method_from_name_checked (domain->domain->mbr.obj.vtable->klass, "DoDomainUnload", -1, 0, error);
  2910. g_assert (method);
  2911. mono_runtime_try_invoke (method, domain->domain, NULL, exc, error);
  2912. if (!is_ok (error)) {
  2913. if (*exc)
  2914. mono_error_cleanup (error);
  2915. else
  2916. *exc = (MonoObject*)mono_error_convert_to_exception (error);
  2917. }
  2918. if (*exc) {
  2919. if (callback != NULL)
  2920. callback (*exc);
  2921. else {
  2922. /* Roll back the state change */
  2923. domain->state = MONO_APPDOMAIN_CREATED;
  2924. mono_domain_set_internal_with_options (caller_domain, TRUE);
  2925. goto exit;
  2926. }
  2927. }
  2928. mono_domain_set_fast (caller_domain, FALSE);
  2929. thread_data = g_new0 (unload_data, 1);
  2930. thread_data->domain = domain;
  2931. thread_data->failure_reason = NULL;
  2932. thread_data->done = FALSE;
  2933. thread_data->refcount = 2; /*Must be 2: unload thread + initiator */
  2934. /*The managed callback finished successfully, now we start tearing down the appdomain*/
  2935. domain->state = MONO_APPDOMAIN_UNLOADING;
  2936. /*
  2937. * First we create a separate thread for unloading, since
  2938. * we might have to abort some threads, including the current one.
  2939. *
  2940. * Have to attach to the runtime so shutdown can wait for this thread.
  2941. *
  2942. * Force it to be attached to avoid racing during shutdown.
  2943. */
  2944. internal = mono_thread_create_internal_handle (mono_get_root_domain (), unload_thread_main, thread_data, MONO_THREAD_CREATE_FLAGS_FORCE_CREATE, error);
  2945. mono_error_assert_ok (error);
  2946. thread_handle = mono_threads_open_thread_handle (MONO_HANDLE_GETVAL (internal, handle));
  2947. /* Wait for the thread */
  2948. while (!thread_data->done && guarded_wait (thread_handle, MONO_INFINITE_WAIT, TRUE) == MONO_THREAD_INFO_WAIT_RET_ALERTED) {
  2949. if (mono_thread_internal_has_appdomain_ref (mono_thread_internal_current (), domain) && (mono_thread_interruption_requested ())) {
  2950. /* The unload thread tries to abort us */
  2951. /* The icall wrapper will execute the abort */
  2952. goto exit;
  2953. }
  2954. }
  2955. if (thread_data->failure_reason) {
  2956. /* Roll back the state change */
  2957. domain->state = MONO_APPDOMAIN_CREATED;
  2958. g_warning ("%s", thread_data->failure_reason);
  2959. *exc = (MonoObject *) mono_get_exception_cannot_unload_appdomain (thread_data->failure_reason);
  2960. g_free (thread_data->failure_reason);
  2961. thread_data->failure_reason = NULL;
  2962. }
  2963. exit:
  2964. mono_threads_close_thread_handle (thread_handle);
  2965. unload_data_unref (thread_data);
  2966. HANDLE_FUNCTION_RETURN ();
  2967. }
  2968. #endif /* ENABLE_NETCORE */
  2969. #ifdef ENABLE_NETCORE
  2970. /* Remember properties so they can be be installed in AppContext during runtime init */
  2971. void
  2972. mono_runtime_register_appctx_properties (int nprops, const char **keys, const char **values)
  2973. {
  2974. n_appctx_props = nprops;
  2975. appctx_keys = g_new0 (gunichar2*, nprops);
  2976. appctx_values = g_new0 (gunichar2*, nprops);
  2977. for (int i = 0; i < nprops; ++i) {
  2978. appctx_keys [i] = g_utf8_to_utf16 (keys [i], strlen (keys [i]), NULL, NULL, NULL);
  2979. appctx_values [i] = g_utf8_to_utf16 (values [i], strlen (values [i]), NULL, NULL, NULL);
  2980. }
  2981. }
  2982. static GENERATE_GET_CLASS_WITH_CACHE (appctx, "System", "AppContext")
  2983. /* Install properties into AppContext */
  2984. void
  2985. mono_runtime_install_appctx_properties (void)
  2986. {
  2987. ERROR_DECL (error);
  2988. gpointer args [3];
  2989. MonoMethod *setup = mono_class_get_method_from_name_checked (mono_class_get_appctx_class (), "Setup", 3, 0, error);
  2990. g_assert (setup);
  2991. // FIXME: TRUSTED_PLATFORM_ASSEMBLIES is very large
  2992. /* internal static unsafe void Setup(char** pNames, char** pValues, int count) */
  2993. args [0] = appctx_keys;
  2994. args [1] = appctx_values;
  2995. args [2] = &n_appctx_props;
  2996. mono_runtime_invoke_checked (setup, NULL, args, error);
  2997. mono_error_assert_ok (error);
  2998. /* No longer needed */
  2999. for (int i = 0; i < n_appctx_props; ++i) {
  3000. g_free (appctx_keys [i]);
  3001. g_free (appctx_values [i]);
  3002. }
  3003. g_free (appctx_keys);
  3004. g_free (appctx_values);
  3005. appctx_keys = NULL;
  3006. appctx_values = NULL;
  3007. }
  3008. #endif