1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934 |
- /**
- * \file
- *
- * Authors:
- * Dietmar Maurer (dietmar@ximian.com)
- * Paolo Molaro (lupus@ximian.com)
- * Patrik Torstensson (patrik.torstensson@labs2.com)
- * Marek Safar (marek.safar@gmail.com)
- * Aleksey Kliger (aleksey@xamarin.com)
- *
- * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
- * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
- * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
- #include <config.h>
- #if defined(TARGET_WIN32) || defined(HOST_WIN32)
- /* Needed for _ecvt_s */
- #define MINGW_HAS_SECURE_API 1
- #include <stdio.h>
- #endif
- #include <glib.h>
- #include <stdarg.h>
- #include <string.h>
- #include <ctype.h>
- #ifdef HAVE_ALLOCA_H
- #include <alloca.h>
- #endif
- #ifdef HAVE_SYS_TIME_H
- #include <sys/time.h>
- #endif
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #if defined (HAVE_WCHAR_H)
- #include <wchar.h>
- #endif
- #include "mono/metadata/icall-internals.h"
- #include "mono/utils/mono-membar.h"
- #include <mono/metadata/object.h>
- #include <mono/metadata/threads.h>
- #include <mono/metadata/threads-types.h>
- #include <mono/metadata/threadpool.h>
- #include <mono/metadata/threadpool-io.h>
- #include <mono/metadata/monitor.h>
- #include <mono/metadata/reflection.h>
- #include <mono/metadata/image-internals.h>
- #include <mono/metadata/assembly.h>
- #include <mono/metadata/assembly-internals.h>
- #include <mono/metadata/tabledefs.h>
- #include <mono/metadata/exception.h>
- #include <mono/metadata/exception-internals.h>
- #include <mono/metadata/w32file.h>
- #include <mono/metadata/console-io.h>
- #include <mono/metadata/w32socket.h>
- #include <mono/metadata/mono-endian.h>
- #include <mono/metadata/tokentype.h>
- #include <mono/metadata/metadata-internals.h>
- #include <mono/metadata/class-internals.h>
- #include <mono/metadata/class-init.h>
- #include <mono/metadata/reflection-internals.h>
- #include <mono/metadata/marshal.h>
- #include <mono/metadata/gc-internals.h>
- #include <mono/metadata/mono-gc.h>
- #include <mono/metadata/rand.h>
- #include <mono/metadata/appdomain-icalls.h>
- #include <mono/metadata/string-icalls.h>
- #include <mono/metadata/debug-helpers.h>
- #include <mono/metadata/w32process.h>
- #include <mono/metadata/environment.h>
- #include <mono/metadata/profiler-private.h>
- #include <mono/metadata/locales.h>
- #include <mono/metadata/filewatcher.h>
- #include <mono/metadata/security.h>
- #include <mono/metadata/mono-config.h>
- #include <mono/metadata/cil-coff.h>
- #include <mono/metadata/number-formatter.h>
- #include <mono/metadata/security-manager.h>
- #include <mono/metadata/security-core-clr.h>
- #include <mono/metadata/mono-perfcounters.h>
- #include <mono/metadata/mono-debug.h>
- #include <mono/metadata/mono-ptr-array.h>
- #include <mono/metadata/verify-internals.h>
- #include <mono/metadata/runtime.h>
- #include <mono/metadata/file-mmap.h>
- #include <mono/metadata/seq-points-data.h>
- #include <mono/metadata/icall-table.h>
- #include <mono/metadata/handle.h>
- #include <mono/metadata/w32mutex.h>
- #include <mono/metadata/w32semaphore.h>
- #include <mono/metadata/w32event.h>
- #include <mono/metadata/abi-details.h>
- #include <mono/metadata/loader-internals.h>
- #include <mono/metadata/unity-utils.h>
- #include <mono/utils/monobitset.h>
- #include <mono/utils/mono-time.h>
- #include <mono/utils/mono-proclib.h>
- #include <mono/utils/mono-string.h>
- #include <mono/utils/mono-error-internals.h>
- #include <mono/utils/mono-mmap.h>
- #include <mono/utils/mono-io-portability.h>
- #include <mono/utils/mono-digest.h>
- #include <mono/utils/bsearch.h>
- #include <mono/utils/mono-os-mutex.h>
- #include <mono/utils/mono-threads.h>
- #include <mono/metadata/w32error.h>
- #include <mono/utils/w32api.h>
- #include <mono/utils/mono-merp.h>
- #include <mono/utils/mono-state.h>
- #include <mono/utils/mono-logger-internals.h>
- #include <mono/utils/mono-math.h>
- #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
- #include <sys/utsname.h>
- #endif
- #include "icall-decl.h"
- #include "mono/utils/mono-threads-coop.h"
- #include "mono/metadata/icall-signatures.h"
- #include "mono/utils/mono-signal-handler.h"
- #if _MSC_VER
- #pragma warning(disable:4047) // FIXME differs in levels of indirection
- #endif
- //#define MONO_DEBUG_ICALLARRAY
- // Inline with CoreCLR heuristics, https://github.com/dotnet/runtime/blob/69e114c1abf91241a0eeecf1ecceab4711b8aa62/src/coreclr/vm/threads.cpp#L6408.
- // Minimum stack size should be sufficient to allow a typical non-recursive call chain to execute,
- // including potential exception handling and garbage collection. Used for probing for available
- // stack space through RuntimeHelpers.EnsureSufficientExecutionStack.
- #if TARGET_SIZEOF_VOID_P == 8
- #define MONO_MIN_EXECUTION_STACK_SIZE (128 * 1024)
- #else
- #define MONO_MIN_EXECUTION_STACK_SIZE (64 * 1024)
- #endif
- #ifdef MONO_DEBUG_ICALLARRAY
- static char debug_icallarray; // 0:uninitialized 1:true 2:false
- static gboolean
- icallarray_print_enabled (void)
- {
- if (!debug_icallarray)
- debug_icallarray = MONO_TRACE_IS_TRACED (G_LOG_LEVEL_DEBUG, MONO_TRACE_ICALLARRAY) ? 1 : 2;
- return debug_icallarray == 1;
- }
- static void
- icallarray_print (const char *format, ...)
- {
- if (!icallarray_print_enabled ())
- return;
- va_list args;
- va_start (args, format);
- g_printv (format, args);
- va_end (args);
- }
- #else
- #define icallarray_print_enabled() (FALSE)
- #define icallarray_print(...) /* nothing */
- #endif
- /* Lazy class loading functions */
- static GENERATE_GET_CLASS_WITH_CACHE (module, "System.Reflection", "Module")
- static void
- array_set_value_impl (MonoArrayHandle arr, MonoObjectHandle value, guint32 pos, gboolean strict_enums, gboolean strict_signs, MonoError *error);
- static MonoArrayHandle
- type_array_from_modifiers (MonoType *type, int optional, MonoError *error);
- static inline MonoBoolean
- is_generic_parameter (MonoType *type)
- {
- return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
- }
- #ifndef HOST_WIN32
- static inline void
- mono_icall_make_platform_path (gchar *path)
- {
- return;
- }
- static inline const gchar *
- mono_icall_get_file_path_prefix (const gchar *path)
- {
- return "file://";
- }
- #endif /* HOST_WIN32 */
- MonoJitICallInfos mono_jit_icall_info;
- MonoObjectHandle
- ves_icall_System_Array_GetValueImpl (MonoArrayHandle array, guint32 pos, MonoError *error)
- {
- MonoClass * const array_class = mono_handle_class (array);
- MonoClass * const element_class = m_class_get_element_class (array_class);
- #ifdef ENABLE_NETCORE
- if (m_class_is_native_pointer (element_class)) {
- mono_error_set_not_supported (error, NULL);
- return NULL_HANDLE;
- }
- #endif
- if (m_class_is_valuetype (element_class)) {
- gsize element_size = mono_array_element_size (array_class);
- gpointer element_address = mono_array_addr_with_size_fast (MONO_HANDLE_RAW (array), element_size, (gsize)pos);
- return mono_value_box_handle (MONO_HANDLE_DOMAIN (array), element_class, element_address, error);
- }
- MonoObjectHandle result = mono_new_null ();
- mono_handle_array_getref (result, array, pos);
- return result;
- }
- MonoObjectHandle
- ves_icall_System_Array_GetValue (MonoArrayHandle arr, MonoArrayHandle indices, MonoError *error)
- {
- MONO_CHECK_ARG_NULL_HANDLE (indices, NULL_HANDLE);
- MonoClass * const indices_class = mono_handle_class (indices);
- MonoClass * const array_class = mono_handle_class (arr);
- g_assert (m_class_get_rank (indices_class) == 1);
- if (MONO_HANDLE_GETVAL (indices, bounds) || MONO_HANDLE_GETVAL (indices, max_length) != m_class_get_rank (array_class)) {
- mono_error_set_argument (error, NULL, NULL);
- return NULL_HANDLE;
- }
- gint32 index = 0;
- if (!MONO_HANDLE_GETVAL (arr, bounds)) {
- MONO_HANDLE_ARRAY_GETVAL (index, indices, gint32, 0);
- if (index < 0 || index >= MONO_HANDLE_GETVAL (arr, max_length)) {
- mono_error_set_index_out_of_range (error);
- return NULL_HANDLE;
- }
- return ves_icall_System_Array_GetValueImpl (arr, index, error);
- }
-
- for (gint32 i = 0; i < m_class_get_rank (array_class); i++) {
- MONO_HANDLE_ARRAY_GETVAL (index, indices, gint32, i);
- if ((index < MONO_HANDLE_GETVAL (arr, bounds [i].lower_bound)) ||
- (index >= (mono_array_lower_bound_t)MONO_HANDLE_GETVAL (arr, bounds [i].length) + MONO_HANDLE_GETVAL (arr, bounds [i].lower_bound))) {
- mono_error_set_index_out_of_range (error);
- return NULL_HANDLE;
- }
- }
- MONO_HANDLE_ARRAY_GETVAL (index, indices, gint32, 0);
- gint32 pos = index - MONO_HANDLE_GETVAL (arr, bounds [0].lower_bound);
- for (gint32 i = 1; i < m_class_get_rank (array_class); i++) {
- MONO_HANDLE_ARRAY_GETVAL (index, indices, gint32, i);
- pos = pos * MONO_HANDLE_GETVAL (arr, bounds [i].length) + index -
- MONO_HANDLE_GETVAL (arr, bounds [i].lower_bound);
- }
- return ves_icall_System_Array_GetValueImpl (arr, pos, error);
- }
- void
- ves_icall_System_Array_SetValueImpl (MonoArrayHandle arr, MonoObjectHandle value, guint32 pos, MonoError *error)
- {
- array_set_value_impl (arr, value, pos, FALSE, TRUE, error);
- }
- static inline void
- set_invalid_cast (MonoError *error, MonoClass *src_class, MonoClass *dst_class)
- {
- mono_get_runtime_callbacks ()->set_cast_details (src_class, dst_class);
- mono_error_set_invalid_cast (error);
- }
- #if ENABLE_NETCORE
- void
- ves_icall_System_Array_SetValueRelaxedImpl (MonoArrayHandle arr, MonoObjectHandle value, guint32 pos, MonoError *error)
- {
- array_set_value_impl (arr, value, pos, FALSE, FALSE, error);
- }
- // Copied from CoreCLR: https://github.com/dotnet/coreclr/blob/d3e39bc2f81e3dbf9e4b96347f62b49d8700336c/src/vm/invokeutil.cpp#L33
- #define PT_Primitive 0x01000000
- static const guint32 primitive_conversions [] = {
- 0x00, // MONO_TYPE_END
- 0x00, // MONO_TYPE_VOID
- PT_Primitive | 0x0004, // MONO_TYPE_BOOLEAN
- PT_Primitive | 0x3F88, // MONO_TYPE_CHAR (W = U2, CHAR, I4, U4, I8, U8, R4, R8)
- PT_Primitive | 0x3550, // MONO_TYPE_I1 (W = I1, I2, I4, I8, R4, R8)
- PT_Primitive | 0x3FE8, // MONO_TYPE_U1 (W = CHAR, U1, I2, U2, I4, U4, I8, U8, R4, R8)
- PT_Primitive | 0x3540, // MONO_TYPE_I2 (W = I2, I4, I8, R4, R8)
- PT_Primitive | 0x3F88, // MONO_TYPE_U2 (W = U2, CHAR, I4, U4, I8, U8, R4, R8)
- PT_Primitive | 0x3500, // MONO_TYPE_I4 (W = I4, I8, R4, R8)
- PT_Primitive | 0x3E00, // MONO_TYPE_U4 (W = U4, I8, R4, R8)
- PT_Primitive | 0x3400, // MONO_TYPE_I8 (W = I8, R4, R8)
- PT_Primitive | 0x3800, // MONO_TYPE_U8 (W = U8, R4, R8)
- PT_Primitive | 0x3000, // MONO_TYPE_R4 (W = R4, R8)
- PT_Primitive | 0x2000, // MONO_TYPE_R8 (W = R8)
- };
- // Copied from CoreCLR: https://github.com/dotnet/coreclr/blob/030a3ea9b8dbeae89c90d34441d4d9a1cf4a7de6/src/vm/invokeutil.h#L176
- static
- gboolean can_primitive_widen (MonoTypeEnum src_type, MonoTypeEnum dest_type)
- {
- if (dest_type > MONO_TYPE_R8 || src_type > MONO_TYPE_R8) {
- return (MONO_TYPE_I == dest_type && MONO_TYPE_I == src_type) || (MONO_TYPE_U == dest_type && MONO_TYPE_U == src_type);
- }
- return ((1 << dest_type) & primitive_conversions [src_type]) != 0;
- }
- // Copied from CoreCLR: https://github.com/dotnet/coreclr/blob/eafa8648ebee92de1380278b15cd5c2b6ef11218/src/vm/array.cpp#L1406
- static MonoTypeEnum
- get_normalized_integral_array_element_type (MonoTypeEnum elementType)
- {
- // Array Primitive types such as E_T_I4 and E_T_U4 are interchangeable
- // Enums with interchangeable underlying types are interchangable
- // BOOL is NOT interchangeable with I1/U1, neither CHAR -- with I2/U2
- switch (elementType) {
- case MONO_TYPE_U1:
- case MONO_TYPE_U2:
- case MONO_TYPE_U4:
- case MONO_TYPE_U8:
- case MONO_TYPE_U:
- return (MonoTypeEnum) (elementType - 1); // normalize to signed type
- }
- return elementType;
- }
- MonoBoolean
- ves_icall_System_Array_CanChangePrimitive (MonoReflectionType *volatile* ref_src_type_handle, MonoReflectionType *volatile* ref_dst_type_handle, MonoBoolean reliable)
- {
- MonoReflectionType* const ref_src_type = *ref_src_type_handle;
- MonoReflectionType* const ref_dst_type = *ref_dst_type_handle;
- MonoType *src_type = ref_src_type->type;
- MonoType *dst_type = ref_dst_type->type;
- g_assert (mono_type_is_primitive (src_type));
- g_assert (mono_type_is_primitive (dst_type));
- MonoTypeEnum normalized_src_type = get_normalized_integral_array_element_type (src_type->type);
- MonoTypeEnum normalized_dst_type = get_normalized_integral_array_element_type (dst_type->type);
- // Allow conversions like int <-> uint
- if (normalized_src_type == normalized_dst_type) {
- return TRUE;
- }
- // Widening is not allowed if reliable is true.
- if (reliable) {
- return FALSE;
- }
- // NOTE we don't use normalized types here so int -> ulong will be false
- // see https://github.com/dotnet/coreclr/pull/25209#issuecomment-505952295
- return can_primitive_widen (src_type->type, dst_type->type);
- }
- #endif
- static void
- array_set_value_impl (MonoArrayHandle arr_handle, MonoObjectHandle value_handle, guint32 pos, gboolean strict_enums, gboolean strict_signs, MonoError *error)
- {
- MonoClass *ac, *vc, *ec;
- gint32 esize, vsize;
- gpointer *ea = NULL, *va = NULL;
- guint64 u64 = 0;
- gint64 i64 = 0;
- gdouble r64 = 0;
- gboolean castOk = FALSE;
- gboolean et_isenum = FALSE;
- gboolean vt_isenum = FALSE;
- error_init (error);
- if (!MONO_HANDLE_IS_NULL (value_handle))
- vc = mono_handle_class (value_handle);
- else
- vc = NULL;
- ac = mono_handle_class (arr_handle);
- ec = m_class_get_element_class (ac);
- esize = mono_array_element_size (ac);
- if (mono_class_is_nullable (ec)) {
- #ifdef ENABLE_NETCORE
- if (vc && m_class_is_primitive (vc) && vc != m_class_get_nullable_elem_class (ec)) {
- // T -> Nullable<T> T must be exact
- set_invalid_cast (error, vc, ec);
- goto leave;
- }
- #endif
- MONO_ENTER_NO_SAFEPOINTS;
- ea = (gpointer*) mono_array_addr_with_size_internal (MONO_HANDLE_RAW (arr_handle), esize, pos);
- if (!MONO_HANDLE_IS_NULL (value_handle))
- va = (gpointer*) mono_object_unbox_internal (MONO_HANDLE_RAW (value_handle));
- mono_nullable_init_unboxed ((guint8*)ea, va, ec);
- MONO_EXIT_NO_SAFEPOINTS;
- goto leave;
- }
- if (MONO_HANDLE_IS_NULL (value_handle)) {
- MONO_ENTER_NO_SAFEPOINTS;
- ea = (gpointer*) mono_array_addr_with_size_internal (MONO_HANDLE_RAW (arr_handle), esize, pos);
- mono_gc_bzero_atomic (ea, esize);
- MONO_EXIT_NO_SAFEPOINTS;
- goto leave;
- }
- #ifdef ENABLE_NETCORE
- #define WIDENING_MSG NULL
- #define WIDENING_ARG NULL
- #else
- #define WIDENING_MSG "not a widening conversion"
- #define WIDENING_ARG "value"
- #endif
- #define NO_WIDENING_CONVERSION G_STMT_START{ \
- mono_error_set_argument (error, WIDENING_ARG, WIDENING_MSG); \
- break; \
- }G_STMT_END
- #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{ \
- if (esize < vsize + (extra)) { \
- mono_error_set_argument (error, WIDENING_ARG, WIDENING_MSG); \
- break; \
- } \
- }G_STMT_END
- #define INVALID_CAST G_STMT_START{ \
- mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
- mono_error_set_invalid_cast (error); \
- break; \
- }G_STMT_END
- MonoTypeEnum et;
- et = m_class_get_byval_arg (ec)->type;
- MonoTypeEnum vt;
- vt = m_class_get_byval_arg (vc)->type;
- /* Check element (destination) type. */
- switch (et) {
- case MONO_TYPE_STRING:
- switch (vt) {
- case MONO_TYPE_STRING:
- break;
- default:
- INVALID_CAST;
- }
- break;
- case MONO_TYPE_BOOLEAN:
- switch (vt) {
- case MONO_TYPE_BOOLEAN:
- break;
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U1:
- case MONO_TYPE_U2:
- case MONO_TYPE_U4:
- case MONO_TYPE_U8:
- case MONO_TYPE_I1:
- case MONO_TYPE_I2:
- case MONO_TYPE_I4:
- case MONO_TYPE_I8:
- case MONO_TYPE_R4:
- case MONO_TYPE_R8:
- NO_WIDENING_CONVERSION;
- break;
- default:
- INVALID_CAST;
- }
- break;
- default:
- break;
- }
- if (!is_ok (error))
- goto leave;
- castOk = mono_object_handle_isinst_mbyref_raw (value_handle, ec, error);
- if (!is_ok (error))
- goto leave;
- if (!m_class_is_valuetype (ec)) {
- if (!castOk)
- INVALID_CAST;
- if (is_ok (error))
- MONO_HANDLE_ARRAY_SETREF (arr_handle, pos, value_handle);
- goto leave;
- }
- if (castOk) {
- MONO_ENTER_NO_SAFEPOINTS;
- ea = (gpointer*) mono_array_addr_with_size_internal (MONO_HANDLE_RAW (arr_handle), esize, pos);
- va = (gpointer*) mono_object_unbox_internal (MONO_HANDLE_RAW (value_handle));
- if (m_class_has_references (ec))
- mono_value_copy_internal (ea, va, ec);
- else
- mono_gc_memmove_atomic (ea, va, esize);
- MONO_EXIT_NO_SAFEPOINTS;
- goto leave;
- }
- if (!m_class_is_valuetype (vc))
- INVALID_CAST;
- if (!is_ok (error))
- goto leave;
- vsize = mono_class_value_size (vc, NULL);
- et_isenum = et == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_class_get_byval_arg (ec)->data.klass);
- vt_isenum = vt == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_class_get_byval_arg (vc)->data.klass);
- #if ENABLE_NETCORE
- if (strict_enums && et_isenum && !vt_isenum) {
- INVALID_CAST;
- goto leave;
- }
- #endif
- if (et_isenum)
- et = mono_class_enum_basetype_internal (m_class_get_byval_arg (ec)->data.klass)->type;
- if (vt_isenum)
- vt = mono_class_enum_basetype_internal (m_class_get_byval_arg (vc)->data.klass)->type;
- #if ENABLE_NETCORE
- // Treat MONO_TYPE_U/I as MONO_TYPE_U8/I8/U4/I4
- #if SIZEOF_VOID_P == 8
- vt = vt == MONO_TYPE_U ? MONO_TYPE_U8 : (vt == MONO_TYPE_I ? MONO_TYPE_I8 : vt);
- et = et == MONO_TYPE_U ? MONO_TYPE_U8 : (et == MONO_TYPE_I ? MONO_TYPE_I8 : et);
- #else
- vt = vt == MONO_TYPE_U ? MONO_TYPE_U4 : (vt == MONO_TYPE_I ? MONO_TYPE_I4 : vt);
- et = et == MONO_TYPE_U ? MONO_TYPE_U4 : (et == MONO_TYPE_I ? MONO_TYPE_I4 : et);
- #endif
- #endif
- #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
- switch (vt) { \
- case MONO_TYPE_U1: \
- case MONO_TYPE_U2: \
- case MONO_TYPE_U4: \
- case MONO_TYPE_U8: \
- case MONO_TYPE_CHAR: \
- CHECK_WIDENING_CONVERSION(0); \
- *(etype *) ea = (etype) u64; \
- break; \
- /* You can't assign a signed value to an unsigned array. */ \
- case MONO_TYPE_I1: \
- case MONO_TYPE_I2: \
- case MONO_TYPE_I4: \
- case MONO_TYPE_I8: \
- if (!strict_signs) { \
- CHECK_WIDENING_CONVERSION(0); \
- *(etype *) ea = (etype) i64; \
- break; \
- } \
- /* You can't assign a floating point number to an integer array. */ \
- case MONO_TYPE_R4: \
- case MONO_TYPE_R8: \
- NO_WIDENING_CONVERSION; \
- break; \
- default: \
- INVALID_CAST; \
- break; \
- } \
- }G_STMT_END
- #define ASSIGN_SIGNED(etype) G_STMT_START{\
- switch (vt) { \
- case MONO_TYPE_I1: \
- case MONO_TYPE_I2: \
- case MONO_TYPE_I4: \
- case MONO_TYPE_I8: \
- CHECK_WIDENING_CONVERSION(0); \
- *(etype *) ea = (etype) i64; \
- break; \
- /* You can assign an unsigned value to a signed array if the array's */ \
- /* element size is larger than the value size. */ \
- case MONO_TYPE_U1: \
- case MONO_TYPE_U2: \
- case MONO_TYPE_U4: \
- case MONO_TYPE_U8: \
- case MONO_TYPE_CHAR: \
- CHECK_WIDENING_CONVERSION(strict_signs ? 1 : 0); \
- *(etype *) ea = (etype) u64; \
- break; \
- /* You can't assign a floating point number to an integer array. */ \
- case MONO_TYPE_R4: \
- case MONO_TYPE_R8: \
- NO_WIDENING_CONVERSION; \
- break; \
- default: \
- INVALID_CAST; \
- break; \
- } \
- }G_STMT_END
- #define ASSIGN_REAL(etype) G_STMT_START{\
- switch (vt) { \
- case MONO_TYPE_R4: \
- case MONO_TYPE_R8: \
- CHECK_WIDENING_CONVERSION(0); \
- *(etype *) ea = (etype) r64; \
- break; \
- /* All integer values fit into a floating point array, so we don't */ \
- /* need to CHECK_WIDENING_CONVERSION here. */ \
- case MONO_TYPE_I1: \
- case MONO_TYPE_I2: \
- case MONO_TYPE_I4: \
- case MONO_TYPE_I8: \
- *(etype *) ea = (etype) i64; \
- break; \
- case MONO_TYPE_U1: \
- case MONO_TYPE_U2: \
- case MONO_TYPE_U4: \
- case MONO_TYPE_U8: \
- case MONO_TYPE_CHAR: \
- *(etype *) ea = (etype) u64; \
- break; \
- default: \
- INVALID_CAST; \
- break; \
- } \
- }G_STMT_END
- MONO_ENTER_NO_SAFEPOINTS;
- g_assert (!MONO_HANDLE_IS_NULL (value_handle));
- g_assert (m_class_is_valuetype (vc));
- va = (gpointer*) mono_object_unbox_internal (MONO_HANDLE_RAW (value_handle));
- ea = (gpointer*) mono_array_addr_with_size_internal (MONO_HANDLE_RAW (arr_handle), esize, pos);
- switch (vt) {
- case MONO_TYPE_U1:
- u64 = *(guint8 *) va;
- break;
- case MONO_TYPE_U2:
- u64 = *(guint16 *) va;
- break;
- case MONO_TYPE_U4:
- u64 = *(guint32 *) va;
- break;
- case MONO_TYPE_U8:
- u64 = *(guint64 *) va;
- break;
- case MONO_TYPE_I1:
- i64 = *(gint8 *) va;
- break;
- case MONO_TYPE_I2:
- i64 = *(gint16 *) va;
- break;
- case MONO_TYPE_I4:
- i64 = *(gint32 *) va;
- break;
- case MONO_TYPE_I8:
- i64 = *(gint64 *) va;
- break;
- case MONO_TYPE_R4:
- r64 = *(gfloat *) va;
- break;
- case MONO_TYPE_R8:
- r64 = *(gdouble *) va;
- break;
- case MONO_TYPE_CHAR:
- u64 = *(guint16 *) va;
- break;
- case MONO_TYPE_BOOLEAN:
- /* Boolean is only compatible with itself. */
- switch (et) {
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U1:
- case MONO_TYPE_U2:
- case MONO_TYPE_U4:
- case MONO_TYPE_U8:
- case MONO_TYPE_I1:
- case MONO_TYPE_I2:
- case MONO_TYPE_I4:
- case MONO_TYPE_I8:
- case MONO_TYPE_R4:
- case MONO_TYPE_R8:
- NO_WIDENING_CONVERSION;
- break;
- default:
- INVALID_CAST;
- }
- break;
- default:
- break;
- }
- /* If we can't do a direct copy, let's try a widening conversion. */
- if (is_ok (error)) {
- switch (et) {
- case MONO_TYPE_CHAR:
- ASSIGN_UNSIGNED (guint16);
- break;
- case MONO_TYPE_U1:
- ASSIGN_UNSIGNED (guint8);
- break;
- case MONO_TYPE_U2:
- ASSIGN_UNSIGNED (guint16);
- break;
- case MONO_TYPE_U4:
- ASSIGN_UNSIGNED (guint32);
- break;
- case MONO_TYPE_U8:
- ASSIGN_UNSIGNED (guint64);
- break;
- case MONO_TYPE_I1:
- ASSIGN_SIGNED (gint8);
- break;
- case MONO_TYPE_I2:
- ASSIGN_SIGNED (gint16);
- break;
- case MONO_TYPE_I4:
- ASSIGN_SIGNED (gint32);
- break;
- case MONO_TYPE_I8:
- ASSIGN_SIGNED (gint64);
- break;
- case MONO_TYPE_R4:
- ASSIGN_REAL (gfloat);
- break;
- case MONO_TYPE_R8:
- ASSIGN_REAL (gdouble);
- break;
- default:
- INVALID_CAST;
- }
- }
- MONO_EXIT_NO_SAFEPOINTS;
- #undef INVALID_CAST
- #undef NO_WIDENING_CONVERSION
- #undef CHECK_WIDENING_CONVERSION
- #undef ASSIGN_UNSIGNED
- #undef ASSIGN_SIGNED
- #undef ASSIGN_REAL
- leave:
- return;
- }
- void
- ves_icall_System_Array_SetValue (MonoArrayHandle arr, MonoObjectHandle value,
- MonoArrayHandle idxs, MonoError *error)
- {
- icallarray_print ("%s\n", __func__);
- MonoArrayBounds dim;
- MonoClass *ac, *ic;
- gint32 idx;
- gint32 i, pos;
- error_init (error);
- if (MONO_HANDLE_IS_NULL (idxs)) {
- #ifdef ENABLE_NETCORE
- mono_error_set_argument_null (error, "indices", "");
- #else
- mono_error_set_argument_null (error, "idxs", "");
- #endif
- return;
- }
- ic = mono_handle_class (idxs);
- ac = mono_handle_class (arr);
- g_assert (m_class_get_rank (ic) == 1);
- if (mono_handle_array_has_bounds (idxs) || MONO_HANDLE_GETVAL (idxs, max_length) != m_class_get_rank (ac)) {
- #ifdef ENABLE_NETCORE
- mono_error_set_argument (error, NULL, "");
- #else
- mono_error_set_argument (error, "idxs", "");
- #endif
- return;
- }
- if (!mono_handle_array_has_bounds (arr)) {
- MONO_HANDLE_ARRAY_GETVAL (idx, idxs, gint32, 0);
- if (idx < 0 || idx >= MONO_HANDLE_GETVAL (arr, max_length)) {
- mono_error_set_exception_instance (error, mono_get_exception_index_out_of_range ());
- return;
- }
- array_set_value_impl (arr, value, idx, TRUE, TRUE, error);
- return;
- }
-
- gint32 ac_rank = m_class_get_rank (ac);
- for (i = 0; i < ac_rank; i++) {
- mono_handle_array_get_bounds_dim (arr, i, &dim);
- MONO_HANDLE_ARRAY_GETVAL (idx, idxs, gint32, i);
- if ((idx < dim.lower_bound) ||
- (idx >= (mono_array_lower_bound_t)dim.length + dim.lower_bound)) {
- mono_error_set_exception_instance (error, mono_get_exception_index_out_of_range ());
- return;
- }
- }
- MONO_HANDLE_ARRAY_GETVAL (idx, idxs, gint32, 0);
- mono_handle_array_get_bounds_dim (arr, 0, &dim);
- pos = idx - dim.lower_bound;
- for (i = 1; i < ac_rank; i++) {
- mono_handle_array_get_bounds_dim (arr, i, &dim);
- MONO_HANDLE_ARRAY_GETVAL (idx, idxs, gint32, i);
- pos = pos * dim.length + idx - dim.lower_bound;
- }
- array_set_value_impl (arr, value, pos, TRUE, TRUE, error);
- }
- #ifdef ENABLE_NETCORE
- void
- ves_icall_System_Array_InternalCreate (MonoArray *volatile* result, MonoType* type, gint32 rank, gint32* pLengths, gint32* pLowerBounds)
- {
- ERROR_DECL (error);
- MonoClass* klass = mono_class_from_mono_type_internal (type);
- if (!mono_class_init_checked (klass, error))
- goto exit;
- if (m_class_get_byval_arg (m_class_get_element_class (klass))->type == MONO_TYPE_VOID) {
- mono_error_set_not_supported (error, "Arrays of System.Void are not supported.");
- goto exit;
- }
- if (type->byref || m_class_is_byreflike (klass)) {
- mono_error_set_not_supported (error, NULL);
- goto exit;
- }
- MonoGenericClass *gklass;
- gklass = mono_class_try_get_generic_class (klass);
- if (is_generic_parameter (type) || mono_class_is_gtd (klass) || (gklass && gklass->context.class_inst->is_open)) {
- mono_error_set_not_supported (error, NULL);
- goto exit;
- }
- /* vectors are not the same as one dimensional arrays with non-zero bounds */
- gboolean bounded;
- bounded = pLowerBounds != NULL && rank == 1 && pLowerBounds [0] != 0;
- MonoClass* aklass;
- aklass = mono_class_create_bounded_array (klass, rank, bounded);
- uintptr_t aklass_rank;
- aklass_rank = m_class_get_rank (aklass);
- uintptr_t* sizes;
- sizes = g_newa (uintptr_t, aklass_rank * 2);
- intptr_t* lower_bounds;
- lower_bounds = (intptr_t*)(sizes + aklass_rank);
- // Copy lengths and lower_bounds from gint32 to [u]intptr_t.
- for (uintptr_t i = 0; i < aklass_rank; ++i) {
- if (pLowerBounds != NULL) {
- lower_bounds [i] = pLowerBounds [i];
- if ((gint64) pLowerBounds [i] + (gint64) pLengths [i] > G_MAXINT32) {
- mono_error_set_argument_out_of_range (error, NULL, "Length + bound must not exceed Int32.MaxValue.");
- goto exit;
- }
- } else {
- lower_bounds [i] = 0;
- }
- sizes [i] = pLengths [i];
- }
- *result = mono_array_new_full_checked (mono_domain_get (), aklass, sizes, lower_bounds, error);
- exit:
- mono_error_set_pending_exception (error);
- }
- #endif
- #ifndef ENABLE_NETCORE
- MonoArrayHandle
- ves_icall_System_Array_CreateInstanceImpl (MonoReflectionTypeHandle type, MonoArrayHandle lengths, MonoArrayHandle bounds, MonoError *error)
- {
- // FIXME? fixed could be used for lengths, bounds.
- icallarray_print ("%s type:%p length:%p bounds:%p\n", __func__, type, lengths, bounds);
- MONO_CHECK_ARG_NULL_HANDLE (type, NULL_HANDLE_ARRAY);
- MONO_CHECK_ARG_NULL_HANDLE (lengths, NULL_HANDLE_ARRAY);
- MONO_CHECK_ARG (lengths, mono_array_handle_length (lengths) > 0, NULL_HANDLE_ARRAY);
- if (!MONO_HANDLE_IS_NULL (bounds))
- MONO_CHECK_ARG (bounds, mono_array_handle_length (lengths) == mono_array_handle_length (bounds), NULL_HANDLE_ARRAY);
- for (uintptr_t i = 0; i < mono_array_handle_length (lengths); ++i) {
- gint32 length = 0;
- MONO_HANDLE_ARRAY_GETVAL (length, lengths, gint32, i);
- if (length < 0) {
- mono_error_set_argument_out_of_range (error, NULL, "MonoArgumentException:NULL");
- return NULL_HANDLE_ARRAY;
- }
- }
- MonoClass *klass = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (type, type));
- if (!mono_class_init_checked (klass, error))
- return NULL_HANDLE_ARRAY;
- if (m_class_get_byval_arg (m_class_get_element_class (klass))->type == MONO_TYPE_VOID) {
- mono_error_set_not_supported (error, "Arrays of System.Void are not supported.");
- return NULL_HANDLE_ARRAY;
- }
- /* vectors are not the same as one dimensional arrays with non-zero bounds */
- gboolean bounded = FALSE;
- if (!MONO_HANDLE_IS_NULL (bounds) && mono_array_handle_length (bounds) == 1) {
- gint32 bound0 = 0;
- MONO_HANDLE_ARRAY_GETVAL (bound0, bounds, gint32, 0);
- bounded = bound0 != 0;
- }
- MonoClass * const aklass = mono_class_create_bounded_array (klass, mono_array_handle_length (lengths), bounded);
- uintptr_t const aklass_rank = m_class_get_rank (aklass);
- uintptr_t * const sizes = g_newa (uintptr_t, aklass_rank);
- intptr_t * const lower_bounds = g_newa (intptr_t, aklass_rank);
- // Copy lengths and lower_bounds from gint32 to [u]intptr_t.
- for (uintptr_t i = 0; i < aklass_rank; ++i) {
- MONO_HANDLE_ARRAY_GETVAL (sizes [i], lengths, gint32, i);
- if (!MONO_HANDLE_IS_NULL (bounds))
- MONO_HANDLE_ARRAY_GETVAL (lower_bounds [i], bounds, gint32, i);
- else
- lower_bounds [i] = 0;
- }
- return mono_array_new_full_handle (MONO_HANDLE_DOMAIN (type), aklass, sizes, lower_bounds, error);
- }
- gint32
- ves_icall_System_Array_GetRank (MonoObjectHandle arr, MonoError *error)
- {
- gint32 const result = m_class_get_rank (mono_handle_class (arr));
- icallarray_print ("%s arr:%p res:%d\n", __func__, MONO_HANDLE_RAW (arr), result);
- return result;
- }
- #endif
- #ifdef ENABLE_NETCORE
- gint32
- ves_icall_System_Array_GetCorElementTypeOfElementType (MonoArrayHandle arr, MonoError *error)
- {
- MonoType *type = mono_type_get_underlying_type (m_class_get_byval_arg (m_class_get_element_class (mono_handle_class (arr))));
- return type->type;
- }
- gint32
- ves_icall_System_Array_IsValueOfElementType (MonoArrayHandle arr, MonoObjectHandle obj, MonoError *error)
- {
- return m_class_get_element_class (mono_handle_class (arr)) == mono_handle_class (obj);
- }
- #endif
- static mono_array_size_t
- mono_array_get_length (MonoArrayHandle arr, gint32 dimension, MonoError *error)
- {
- if (dimension < 0 || dimension >= m_class_get_rank (mono_handle_class (arr))) {
- mono_error_set_index_out_of_range (error);
- return 0;
- }
- return MONO_HANDLE_GETVAL (arr, bounds) ? MONO_HANDLE_GETVAL (arr, bounds [dimension].length)
- : MONO_HANDLE_GETVAL (arr, max_length);
- }
- gint32
- ves_icall_System_Array_GetLength (MonoArrayHandle arr, gint32 dimension, MonoError *error)
- {
- icallarray_print ("%s arr:%p dimension:%d\n", __func__, MONO_HANDLE_RAW (arr), (int)dimension);
- mono_array_size_t const length = mono_array_get_length (arr, dimension, error);
- if (length > G_MAXINT32) {
- mono_error_set_overflow (error);
- return 0;
- }
- return (gint32)length;
- }
- #ifndef ENABLE_NETCORE
- gint64
- ves_icall_System_Array_GetLongLength (MonoArrayHandle arr, gint32 dimension, MonoError *error)
- {
- icallarray_print ("%s arr:%p dimension:%d\n", __func__, MONO_HANDLE_RAW (arr), (int)dimension);
- return (gint64)mono_array_get_length (arr, dimension, error);
- }
- #endif
- gint32
- ves_icall_System_Array_GetLowerBound (MonoArrayHandle arr, gint32 dimension, MonoError *error)
- {
- icallarray_print ("%s arr:%p dimension:%d\n", __func__, MONO_HANDLE_RAW (arr), (int)dimension);
- if (dimension < 0 || dimension >= m_class_get_rank (mono_handle_class (arr))) {
- mono_error_set_index_out_of_range (error);
- return 0;
- }
- return MONO_HANDLE_GETVAL (arr, bounds) ? MONO_HANDLE_GETVAL (arr, bounds [dimension].lower_bound)
- : 0;
- }
- #ifndef ENABLE_NETCORE
- void
- ves_icall_System_Array_ClearInternal (MonoArrayHandle arr, int idx, int length, MonoError *error)
- {
- icallarray_print ("%s arr:%p idx:%d len:%d\n", __func__, MONO_HANDLE_RAW (arr), (int)idx, (int)length);
- int sz = mono_array_element_size (mono_handle_class (arr));
- mono_gc_bzero_atomic (mono_array_addr_with_size_fast (MONO_HANDLE_RAW (arr), sz, idx), length * sz);
- }
- #endif
- MonoBoolean
- ves_icall_System_Array_FastCopy (MonoArrayHandle source, int source_idx, MonoArrayHandle dest, int dest_idx, int length, MonoError *error)
- {
- MonoVTable * const src_vtable = MONO_HANDLE_GETVAL (source, obj.vtable);
- MonoVTable * const dest_vtable = MONO_HANDLE_GETVAL (dest, obj.vtable);
- if (src_vtable->rank != dest_vtable->rank)
- return FALSE;
- MonoArrayBounds *source_bounds = MONO_HANDLE_GETVAL (source, bounds);
- MonoArrayBounds *dest_bounds = MONO_HANDLE_GETVAL (dest, bounds);
- for (int i = 0; i < src_vtable->rank; i++) {
- if ((source_bounds && source_bounds [i].lower_bound > 0) ||
- (dest_bounds && dest_bounds [i].lower_bound > 0))
- return FALSE;
- }
- /* there's no integer overflow since mono_array_length_internal returns an unsigned integer */
- if ((dest_idx + length > mono_array_handle_length (dest)) ||
- (source_idx + length > mono_array_handle_length (source)))
- return FALSE;
- MonoClass * const src_class = m_class_get_element_class (src_vtable->klass);
- MonoClass * const dest_class = m_class_get_element_class (dest_vtable->klass);
- /*
- * Handle common cases.
- */
- /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
- We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
- */
- if (src_class == mono_defaults.object_class && m_class_is_valuetype (dest_class))
- return FALSE;
- /* Check if we're copying a char[] <==> (u)short[] */
- if (src_class != dest_class) {
- if (m_class_is_valuetype (dest_class) || m_class_is_enumtype (dest_class) ||
- m_class_is_valuetype (src_class) || m_class_is_valuetype (src_class))
- return FALSE;
- /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
- if (!mono_class_is_subclass_of_internal (src_class, dest_class, FALSE))
- return FALSE;
- if (m_class_is_native_pointer (src_class) || m_class_is_native_pointer (dest_class))
- return FALSE;
- }
- if (m_class_is_valuetype (dest_class)) {
- gsize const element_size = mono_array_element_size (MONO_HANDLE_GETVAL (source, obj.vtable->klass));
- MONO_ENTER_NO_SAFEPOINTS; // gchandle would also work here, is slow, breaks profiler tests.
- gconstpointer const source_addr =
- mono_array_addr_with_size_fast (MONO_HANDLE_RAW (source), element_size, source_idx);
- if (m_class_has_references (dest_class)) {
- mono_value_copy_array_handle (dest, dest_idx, source_addr, length);
- } else {
- gpointer const dest_addr =
- mono_array_addr_with_size_fast (MONO_HANDLE_RAW (dest), element_size, dest_idx);
- mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
- }
- MONO_EXIT_NO_SAFEPOINTS;
- } else {
- mono_array_handle_memcpy_refs (dest, dest_idx, source, source_idx, length);
- }
- return TRUE;
- }
- void
- ves_icall_System_Array_GetGenericValue_icall (MonoArray **arr, guint32 pos, gpointer value)
- {
- icallarray_print ("%s arr:%p pos:%u value:%p\n", __func__, *arr, pos, value);
- MONO_REQ_GC_UNSAFE_MODE; // because of gpointer value
- MonoClass * const ac = mono_object_class (*arr);
- gsize const esize = mono_array_element_size (ac);
- gconstpointer * const ea = (gconstpointer*)((char*)(*arr)->vector + (pos * esize));
- mono_gc_memmove_atomic (value, ea, esize);
- }
- void
- ves_icall_System_Array_SetGenericValue_icall (MonoArray **arr, guint32 pos, gpointer value)
- {
- icallarray_print ("%s arr:%p pos:%u value:%p\n", __func__, *arr, pos, value);
- MONO_REQ_GC_UNSAFE_MODE; // because of gpointer value
- MonoClass * const ac = mono_object_class (*arr);
- MonoClass * const ec = m_class_get_element_class (ac);
- gsize const esize = mono_array_element_size (ac);
- gpointer * const ea = (gpointer*)((char*)(*arr)->vector + (pos * esize));
- if (MONO_TYPE_IS_REFERENCE (m_class_get_byval_arg (ec))) {
- g_assert (esize == sizeof (gpointer));
- mono_gc_wbarrier_generic_store_internal (ea, *(MonoObject **)value);
- } else {
- g_assert (m_class_is_inited (ec));
- g_assert (esize == mono_class_value_size (ec, NULL));
- if (m_class_has_references (ec))
- mono_gc_wbarrier_value_copy_internal (ea, value, 1, ec);
- else
- mono_gc_memmove_atomic (ea, value, esize);
- }
- }
- void
- #if ENABLE_NETCORE
- ves_icall_System_Runtime_RuntimeImports_Memmove (guint8 *destination, guint8 *source, size_t byte_count)
- #else
- ves_icall_System_Runtime_RuntimeImports_Memmove (guint8 *destination, guint8 *source, guint byte_count)
- #endif
- {
- mono_gc_memmove_atomic (destination, source, byte_count);
- }
- #if ENABLE_NETCORE
- void
- ves_icall_System_Buffer_BulkMoveWithWriteBarrier (guint8 *destination, guint8 *source, size_t len, MonoType *type)
- {
- if (MONO_TYPE_IS_REFERENCE (type))
- mono_gc_wbarrier_arrayref_copy_internal (destination, source, (guint)len);
- else
- mono_gc_wbarrier_value_copy_internal (destination, source, (guint)len, mono_class_from_mono_type_internal (type));
- }
- #else
- void
- ves_icall_System_Runtime_RuntimeImports_Memmove_wbarrier (guint8 *destination, guint8 *source, guint len, MonoType *type)
- {
- if (MONO_TYPE_IS_REFERENCE (type))
- mono_gc_wbarrier_arrayref_copy_internal (destination, source, len);
- else
- mono_gc_wbarrier_value_copy_internal (destination, source, len, mono_class_from_mono_type_internal (type));
- }
- #endif
- void
- #if ENABLE_NETCORE
- ves_icall_System_Runtime_RuntimeImports_ZeroMemory (guint8 *p, size_t byte_length)
- #else
- ves_icall_System_Runtime_RuntimeImports_ZeroMemory (guint8 *p, guint byte_length)
- #endif
- {
- memset (p, 0, byte_length);
- }
- void
- ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArrayHandle array, MonoClassField *field_handle, MonoError *error)
- {
- MonoClass *klass = mono_handle_class (array);
- guint32 size = mono_array_element_size (klass);
- MonoType *type = mono_type_get_underlying_type (m_class_get_byval_arg (m_class_get_element_class (klass)));
- int align;
- const char *field_data;
- if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
- mono_error_set_argument (error, "array", "Cannot initialize array of non-primitive type");
- return;
- }
- MonoType *field_type = mono_field_get_type_checked (field_handle, error);
- if (!field_type)
- return;
- if (!(field_type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
- mono_error_set_argument_format (error, "field_handle", "Field '%s' doesn't have an RVA", mono_field_get_name (field_handle));
- return;
- }
- size *= MONO_HANDLE_GETVAL(array, max_length);
- field_data = mono_field_get_data (field_handle);
- if (size > mono_type_size (field_handle->type, &align)) {
- mono_error_set_argument (error, "field_handle", "Field not large enough to fill array");
- return;
- }
- #if G_BYTE_ORDER != G_LITTLE_ENDIAN
- #define SWAP(n) { \
- guint ## n *data = (guint ## n *) mono_array_addr_internal (MONO_HANDLE_RAW(array), char, 0); \
- guint ## n *src = (guint ## n *) field_data; \
- int i, \
- nEnt = (size / sizeof(guint ## n)); \
- \
- for (i = 0; i < nEnt; i++) { \
- data[i] = read ## n (&src[i]); \
- } \
- }
- /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
- switch (type->type) {
- case MONO_TYPE_CHAR:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- SWAP (16);
- break;
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_R4:
- SWAP (32);
- break;
- case MONO_TYPE_I8:
- case MONO_TYPE_U8:
- case MONO_TYPE_R8:
- SWAP (64);
- break;
- default:
- memcpy (mono_array_addr_internal (MONO_HANDLE_RAW(array), char, 0), field_data, size);
- break;
- }
- #else
- memcpy (mono_array_addr_internal (MONO_HANDLE_RAW(array), char, 0), field_data, size);
- #endif
- }
- gint
- ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
- {
- return offsetof (MonoString, chars);
- }
- MonoObjectHandle
- ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObjectHandle obj, MonoError *error)
- {
- if (MONO_HANDLE_IS_NULL (obj) || !m_class_is_valuetype (mono_handle_class (obj)))
- return obj;
- return mono_object_clone_handle (obj, error);
- }
- void
- ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle, MonoError *error)
- {
- MonoClass *klass;
- MonoVTable *vtable;
- MONO_CHECK_ARG_NULL (handle,);
- klass = mono_class_from_mono_type_internal (handle);
- MONO_CHECK_ARG (handle, klass,);
- if (mono_class_is_gtd (klass))
- return;
- vtable = mono_class_vtable_checked (mono_domain_get (), klass, error);
- return_if_nok (error);
- /* This will call the type constructor */
- mono_runtime_class_init_full (vtable, error);
- }
- void
- ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image, MonoError *error)
- {
- mono_image_check_for_module_cctor (image);
- if (!image->has_module_cctor)
- return;
- MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, error);
- return_if_nok (error);
- MonoVTable * vtable = mono_class_vtable_checked (mono_domain_get (), module_klass, error);
- return_if_nok (error);
- mono_runtime_class_init_full (vtable, error);
- }
- #ifdef ENABLE_NETCORE
- MonoBoolean
- ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
- {
- MonoThreadInfo *thread = mono_thread_info_current ();
- void *current = &thread;
- // Stack upper/lower bound should have been calculated and set as part of register_thread.
- // If not, we are optimistic and assume there is enough room.
- if (!thread->stack_start_limit || !thread->stack_end)
- return TRUE;
- // Stack start limit is stack lower bound. Make sure there is enough room left.
- void *limit = ((uint8_t *)thread->stack_start_limit) + ALIGN_TO (MONO_STACK_OVERFLOW_GUARD_SIZE + MONO_MIN_EXECUTION_STACK_SIZE, ((gssize)mono_pagesize ()));
- if (current < limit)
- return FALSE;
- return TRUE;
- }
- #else
- MonoBoolean
- ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
- {
- return mono_thread_has_sufficient_execution_stack ();
- }
- #endif
- #ifdef ENABLE_NETCORE
- MonoObjectHandle
- ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetUninitializedObjectInternal (MonoType *handle, MonoError *error)
- {
- MonoClass *klass;
- MonoVTable *vtable;
- g_assert (handle);
- klass = mono_class_from_mono_type_internal (handle);
- if (m_class_is_string (klass)) {
- mono_error_set_argument (error, NULL, NULL);
- return NULL_HANDLE;
- }
- if (mono_class_is_array (klass) || mono_class_is_pointer (klass) || handle->byref) {
- mono_error_set_argument (error, NULL, NULL);
- return NULL_HANDLE;
- }
- if (MONO_TYPE_IS_VOID (handle)) {
- mono_error_set_argument (error, NULL, NULL);
- return NULL_HANDLE;
- }
- if (m_class_is_abstract (klass) || m_class_is_interface (klass) || m_class_is_gtd (klass)) {
- mono_error_set_member_access (error, NULL, NULL);
- return NULL_HANDLE;
- }
- if (m_class_is_byreflike (klass)) {
- mono_error_set_not_supported (error, NULL, NULL);
- return NULL_HANDLE;
- }
- if (!mono_class_is_before_field_init (klass)) {
- vtable = mono_class_vtable_checked (mono_domain_get (), klass, error);
- return_val_if_nok (error, NULL_HANDLE);
- mono_runtime_class_init_full (vtable, error);
- return_val_if_nok (error, NULL_HANDLE);
- }
- if (m_class_is_nullable (klass))
- return mono_object_new_handle (mono_domain_get (), m_class_get_nullable_elem_class (klass), error);
- else
- return mono_object_new_handle (mono_domain_get (), klass, error);
- }
- void
- ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_PrepareMethod (MonoMethod *method, gpointer inst_types, int n_inst_types, MonoError *error)
- {
- if (method->flags & METHOD_ATTRIBUTE_ABSTRACT) {
- mono_error_set_argument (error, NULL, NULL);
- return;
- }
- MonoGenericContainer *container = NULL;
- if (method->is_generic)
- container = mono_method_get_generic_container (method);
- else if (m_class_is_gtd (method->klass))
- container = mono_class_get_generic_container (method->klass);
- if (container) {
- int nparams = container->type_argc + (container->parent ? container->parent->type_argc : 0);
- if (nparams != n_inst_types) {
- mono_error_set_argument (error, NULL, NULL);
- return;
- }
- }
- // FIXME: Implement
- }
- #endif
- MonoObjectHandle
- ves_icall_System_Object_MemberwiseClone (MonoObjectHandle this_obj, MonoError *error)
- {
- return mono_object_clone_handle (this_obj, error);
- }
- gint32
- ves_icall_System_ValueType_InternalGetHashCode (MonoObjectHandle this_obj, MonoArrayHandleOut fields, MonoError *error)
- {
- MonoClass *klass;
- MonoClassField **unhandled = NULL;
- int count = 0;
- gint32 result = (int)(gsize)mono_defaults.int32_class;
- MonoClassField* field;
- gpointer iter;
- klass = mono_handle_class (this_obj);
- if (mono_class_num_fields (klass) == 0)
- return result;
- /*
- * Compute the starting value of the hashcode for fields of primitive
- * types, and return the remaining fields in an array to the managed side.
- * This way, we can avoid costly reflection operations in managed code.
- */
- iter = NULL;
- while ((field = mono_class_get_fields_internal (klass, &iter))) {
- if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
- continue;
- if (mono_field_is_deleted (field))
- continue;
- gpointer addr = (guint8*)MONO_HANDLE_RAW (this_obj) + field->offset;
- /* FIXME: Add more types */
- switch (field->type->type) {
- case MONO_TYPE_I4:
- result ^= *(gint32*)addr;
- break;
- case MONO_TYPE_PTR:
- result ^= mono_aligned_addr_hash (*(gpointer*)addr);
- break;
- case MONO_TYPE_STRING: {
- MonoString *s;
- s = *(MonoString**)addr;
- if (s != NULL)
- result ^= mono_string_hash_internal (s);
- break;
- }
- default:
- if (!unhandled)
- unhandled = g_newa (MonoClassField*, mono_class_num_fields (klass));
- unhandled [count ++] = field;
- }
- }
- if (unhandled) {
- MonoArrayHandle fields_arr = mono_array_new_handle (mono_domain_get (), mono_defaults.object_class, count, error);
- return_val_if_nok (error, 0);
- MONO_HANDLE_ASSIGN (fields, fields_arr);
- MonoObjectHandle h = MONO_HANDLE_NEW (MonoObject, NULL);
- for (int i = 0; i < count; ++i) {
- MonoObject *o = mono_field_get_value_object_checked (mono_handle_domain (this_obj), unhandled [i], MONO_HANDLE_RAW (this_obj), error);
- return_val_if_nok (error, 0);
- MONO_HANDLE_ASSIGN_RAW (h, o);
- mono_array_handle_setref (fields_arr, i, h);
- }
- } else {
- MONO_HANDLE_ASSIGN (fields, NULL_HANDLE);
- }
- return result;
- }
- MonoBoolean
- ves_icall_System_ValueType_Equals (MonoObjectHandle this_obj, MonoObjectHandle that, MonoArrayHandleOut fields, MonoError *error)
- {
- MonoClass *klass;
- MonoClassField **unhandled = NULL;
- MonoClassField* field;
- gpointer iter;
- int count = 0;
- MONO_CHECK_ARG_NULL_HANDLE (that, FALSE);
- MONO_HANDLE_ASSIGN (fields, NULL_HANDLE);
- if (mono_handle_vtable (this_obj) != mono_handle_vtable (that))
- return FALSE;
- klass = mono_handle_class (this_obj);
- if (m_class_is_enumtype (klass) && mono_class_enum_basetype_internal (klass) && mono_class_enum_basetype_internal (klass)->type == MONO_TYPE_I4)
- return *(gint32*)mono_handle_get_data_unsafe (this_obj) == *(gint32*)mono_handle_get_data_unsafe (that);
- /*
- * Do the comparison for fields of primitive type and return a result if
- * possible. Otherwise, return the remaining fields in an array to the
- * managed side. This way, we can avoid costly reflection operations in
- * managed code.
- */
- iter = NULL;
- while ((field = mono_class_get_fields_internal (klass, &iter))) {
- if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
- continue;
- if (mono_field_is_deleted (field))
- continue;
- guint8 *this_field = (guint8 *)MONO_HANDLE_RAW (this_obj) + field->offset;
- guint8 *that_field = (guint8 *)MONO_HANDLE_RAW (that) + field->offset;
- #define UNALIGNED_COMPARE(type) \
- do { \
- type left, right; \
- memcpy (&left, this_field, sizeof (type)); \
- memcpy (&right, that_field, sizeof (type)); \
- if (left != right) \
- return FALSE; \
- } while (0)
- /* FIXME: Add more types */
- switch (field->type->type) {
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- case MONO_TYPE_BOOLEAN:
- if (*this_field != *that_field)
- return FALSE;
- break;
- case MONO_TYPE_U2:
- case MONO_TYPE_I2:
- case MONO_TYPE_CHAR:
- #ifdef NO_UNALIGNED_ACCESS
- if (G_UNLIKELY ((intptr_t) this_field & 1 || (intptr_t) that_field & 1))
- UNALIGNED_COMPARE (gint16);
- else
- #endif
- if (*(gint16 *) this_field != *(gint16 *) that_field)
- return FALSE;
- break;
- case MONO_TYPE_U4:
- case MONO_TYPE_I4:
- #ifdef NO_UNALIGNED_ACCESS
- if (G_UNLIKELY ((intptr_t) this_field & 3 || (intptr_t) that_field & 3))
- UNALIGNED_COMPARE (gint32);
- else
- #endif
- if (*(gint32 *) this_field != *(gint32 *) that_field)
- return FALSE;
- break;
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- #ifdef NO_UNALIGNED_ACCESS
- if (G_UNLIKELY ((intptr_t) this_field & 7 || (intptr_t) that_field & 7))
- UNALIGNED_COMPARE (gint64);
- else
- #endif
- if (*(gint64 *) this_field != *(gint64 *) that_field)
- return FALSE;
- break;
- case MONO_TYPE_R4: {
- float d1, d2;
- #ifdef NO_UNALIGNED_ACCESS
- memcpy (&d1, this_field, sizeof (float));
- memcpy (&d2, that_field, sizeof (float));
- #else
- d1 = *(float *) this_field;
- d2 = *(float *) that_field;
- #endif
- if (d1 != d2 && !(mono_isnan (d1) && mono_isnan (d2)))
- return FALSE;
- break;
- }
- case MONO_TYPE_R8: {
- double d1, d2;
- #ifdef NO_UNALIGNED_ACCESS
- memcpy (&d1, this_field, sizeof (double));
- memcpy (&d2, that_field, sizeof (double));
- #else
- d1 = *(double *) this_field;
- d2 = *(double *) that_field;
- #endif
- if (d1 != d2 && !(mono_isnan (d1) && mono_isnan (d2)))
- return FALSE;
- break;
- }
- case MONO_TYPE_PTR:
- #ifdef NO_UNALIGNED_ACCESS
- if (G_UNLIKELY ((intptr_t) this_field & 7 || (intptr_t) that_field & 7))
- UNALIGNED_COMPARE (gpointer);
- else
- #endif
- if (*(gpointer *) this_field != *(gpointer *) that_field)
- return FALSE;
- break;
- case MONO_TYPE_STRING: {
- MonoString *s1, *s2;
- guint32 s1len, s2len;
- s1 = *(MonoString**)this_field;
- s2 = *(MonoString**)that_field;
- if (s1 == s2)
- break;
- if ((s1 == NULL) || (s2 == NULL))
- return FALSE;
- s1len = mono_string_length_internal (s1);
- s2len = mono_string_length_internal (s2);
- if (s1len != s2len)
- return FALSE;
- if (memcmp (mono_string_chars_internal (s1), mono_string_chars_internal (s2), s1len * sizeof (gunichar2)) != 0)
- return FALSE;
- break;
- }
- default:
- if (!unhandled)
- unhandled = g_newa (MonoClassField*, mono_class_num_fields (klass));
- unhandled [count ++] = field;
- }
- #undef UNALIGNED_COMPARE
- if (m_class_is_enumtype (klass))
- /* enums only have one non-static field */
- break;
- }
- if (unhandled) {
- MonoArrayHandle fields_arr = mono_array_new_handle (mono_domain_get (), mono_defaults.object_class, count * 2, error);
- return_val_if_nok (error, 0);
- MONO_HANDLE_ASSIGN (fields, fields_arr);
- MonoObjectHandle h = MONO_HANDLE_NEW (MonoObject, NULL);
- for (int i = 0; i < count; ++i) {
- MonoObject *o = mono_field_get_value_object_checked (mono_handle_domain (this_obj), unhandled [i], MONO_HANDLE_RAW (this_obj), error);
- return_val_if_nok (error, FALSE);
- MONO_HANDLE_ASSIGN_RAW (h, o);
- mono_array_handle_setref (fields_arr, i * 2, h);
- o = mono_field_get_value_object_checked (mono_handle_domain (this_obj), unhandled [i], MONO_HANDLE_RAW (that), error);
- return_val_if_nok (error, FALSE);
- MONO_HANDLE_ASSIGN_RAW (h, o);
- mono_array_handle_setref (fields_arr, (i * 2) + 1, h);
- }
- return FALSE;
- } else {
- return TRUE;
- }
- }
- #ifndef ENABLE_NETCORE
- MonoReflectionTypeHandle
- ves_icall_System_Object_GetType (MonoObjectHandle obj, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (obj);
- MonoClass *klass = mono_handle_class (obj);
- #ifndef DISABLE_REMOTING
- if (mono_class_is_transparent_proxy (klass)) {
- MonoTransparentProxyHandle proxy_obj = MONO_HANDLE_CAST (MonoTransparentProxy, obj);
- MonoRemoteClass *remote_class = MONO_HANDLE_GETVAL (proxy_obj, remote_class);
- /* If it's a transparent proxy for an interface, return the
- * interface type, not the unhelpful proxy_class class (which
- * is just MarshalByRefObject). */
- MonoType *proxy_type =
- mono_remote_class_is_interface_proxy (remote_class) ?
- m_class_get_byval_arg (remote_class->interfaces[0]) :
- m_class_get_byval_arg (remote_class->proxy_class);
- return mono_type_get_object_handle (domain, proxy_type, error);
- } else
- #endif
- return mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
- }
- #endif
- static gboolean
- get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
- {
- MonoMethod **dest = (MonoMethod **)data;
- /* skip unmanaged frames */
- if (!managed)
- return FALSE;
- if (!(*dest)) {
- if (!strcmp (m_class_get_name_space (m->klass), "System.Reflection"))
- return FALSE;
- *dest = m;
- return TRUE;
- }
- return FALSE;
- }
- static gboolean
- in_corlib_name_space (MonoClass *klass, const char *name_space)
- {
- return m_class_get_image (klass) == mono_defaults.corlib &&
- !strcmp (m_class_get_name_space (klass), name_space);
- }
- static gboolean
- get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
- {
- MonoMethod **dest = (MonoMethod **)data;
- /* skip unmanaged frames */
- if (!managed)
- return FALSE;
- if (m->wrapper_type != MONO_WRAPPER_NONE)
- return FALSE;
- if (m == *dest) {
- *dest = NULL;
- return FALSE;
- }
- if (in_corlib_name_space (m->klass, "System.Reflection"))
- return FALSE;
- if (!(*dest)) {
- *dest = m;
- return TRUE;
- }
- return FALSE;
- }
- static gboolean
- get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
- {
- MonoMethod **dest = (MonoMethod **)data;
- /* skip unmanaged frames */
- if (!managed)
- return FALSE;
- if (m->wrapper_type != MONO_WRAPPER_NONE)
- return FALSE;
- if (m == *dest) {
- *dest = NULL;
- return FALSE;
- }
- if (in_corlib_name_space (m->klass, "System.Reflection") || in_corlib_name_space (m->klass, "System"))
- return FALSE;
- if (!(*dest)) {
- *dest = m;
- return TRUE;
- }
- return FALSE;
- }
- /**
- * mono_runtime_get_caller_no_system_or_reflection:
- *
- * Walk the stack of the current thread and find the first managed method that
- * is not in the mscorlib System or System.Reflection namespace. This skips
- * unmanaged callers and wrapper methods.
- *
- * \returns a pointer to the \c MonoMethod or NULL if we walked past all the
- * callers.
- */
- MonoMethod*
- mono_runtime_get_caller_no_system_or_reflection (void)
- {
- MonoMethod *dest = NULL;
- mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
- return dest;
- }
- /*
- * mono_runtime_get_caller_from_stack_mark:
- *
- * Walk the stack and return the assembly of the method referenced
- * by the stack mark STACK_MARK.
- */
- MonoAssembly*
- mono_runtime_get_caller_from_stack_mark (MonoStackCrawlMark *stack_mark)
- {
- // FIXME: Use the stack mark
- MonoMethod *dest = NULL;
- mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
- if (dest)
- return m_class_get_image (dest->klass)->assembly;
- else
- return NULL;
- }
- static MonoReflectionTypeHandle
- type_from_parsed_name (MonoTypeNameParse *info, MonoStackCrawlMark *stack_mark, MonoBoolean ignoreCase, MonoAssembly **caller_assembly, MonoError *error)
- {
- MonoMethod *m;
- MonoType *type = NULL;
- MonoAssembly *assembly = NULL;
- gboolean type_resolve = FALSE;
- MonoImage *rootimage = NULL;
- MonoAssemblyLoadContext *alc = mono_domain_ambient_alc (mono_domain_get ());
- error_init (error);
- /*
- * We must compute the calling assembly as type loading must happen under a metadata context.
- * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
- * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
- */
- m = mono_method_get_last_managed ();
- if (m && m_class_get_image (m->klass) != mono_defaults.corlib) {
- /* Happens with inlining */
- assembly = m_class_get_image (m->klass)->assembly;
- } else {
- assembly = mono_runtime_get_caller_from_stack_mark (stack_mark);
- }
- if (assembly) {
- type_resolve = TRUE;
- rootimage = assembly->image;
- } else {
- // FIXME: once wasm can use stack marks, consider turning all this into an assert
- g_warning (G_STRLOC);
- }
- *caller_assembly = assembly;
- if (info->assembly.name) {
- MonoAssemblyByNameRequest req;
- mono_assembly_request_prepare_byname (&req, MONO_ASMCTX_DEFAULT, alc);
- req.requesting_assembly = assembly;
- req.basedir = assembly ? assembly->basedir : NULL;
- assembly = mono_assembly_request_byname (&info->assembly, &req, NULL);
- }
- if (assembly) {
- /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
- type = mono_reflection_get_type_checked (alc, rootimage, assembly->image, info, ignoreCase, TRUE, &type_resolve, error);
- goto_if_nok (error, fail);
- }
- // XXXX - aleksey -
- // Say we're looking for System.Generic.Dict<int, Local>
- // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
- // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
- // is messed up when we go to construct the Local as the type arg...
- //
- // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
- // as the root and then even the detour into generics would still not cause issues when we went to load Local.
- if (!info->assembly.name && !type) {
- /* try mscorlib */
- type = mono_reflection_get_type_checked (alc, rootimage, NULL, info, ignoreCase, TRUE, &type_resolve, error);
- goto_if_nok (error, fail);
- }
- if (assembly && !type && type_resolve) {
- type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
- type = mono_reflection_get_type_checked (alc, rootimage, assembly->image, info, ignoreCase, TRUE, &type_resolve, error);
- goto_if_nok (error, fail);
- }
- if (!type)
- goto fail;
- return mono_type_get_object_handle (mono_domain_get (), type, error);
- fail:
- return MONO_HANDLE_NEW (MonoReflectionType, NULL);
- }
- MonoReflectionTypeHandle
- ves_icall_System_RuntimeTypeHandle_internal_from_name (MonoStringHandle name,
- MonoStackCrawlMark *stack_mark,
- MonoReflectionAssemblyHandle callerAssembly,
- MonoBoolean throwOnError,
- MonoBoolean ignoreCase,
- MonoBoolean reflectionOnly,
- MonoError *error)
- {
- MonoTypeNameParse info;
- gboolean free_info = FALSE;
- MonoAssembly *caller_assembly;
- MonoReflectionTypeHandle type = MONO_HANDLE_NEW (MonoReflectionType, NULL);
- /* The callerAssembly argument is unused for now */
- char *str = mono_string_handle_to_utf8 (name, error);
- goto_if_nok (error, leave);
- free_info = TRUE;
- if (!mono_reflection_parse_type_checked (str, &info, error))
- goto leave;
- /* mono_reflection_parse_type() mangles the string */
- MONO_HANDLE_ASSIGN (type, type_from_parsed_name (&info, (MonoStackCrawlMark*)stack_mark, ignoreCase, &caller_assembly, error));
- goto_if_nok (error, leave);
- if (MONO_HANDLE_IS_NULL (type)) {
- if (throwOnError) {
- char *tname = info.name_space ? g_strdup_printf ("%s.%s", info.name_space, info.name) : g_strdup (info.name);
- char *aname;
- if (info.assembly.name)
- aname = mono_stringify_assembly_name (&info.assembly);
- else if (caller_assembly)
- aname = mono_stringify_assembly_name (mono_assembly_get_name_internal (caller_assembly));
- else
- aname = g_strdup ("");
- mono_error_set_type_load_name (error, tname, aname, "");
- }
- goto leave;
- }
-
- leave:
- if (free_info)
- mono_reflection_free_type_info (&info);
- g_free (str);
- if (!is_ok (error)) {
- if (!throwOnError) {
- mono_error_cleanup (error);
- error_init (error);
- }
- return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
- } else
- return type;
- }
- MonoReflectionTypeHandle
- ves_icall_System_Type_internal_from_handle (MonoType *handle, MonoError *error)
- {
- MonoDomain *domain = mono_domain_get ();
- return mono_type_get_object_handle (domain, handle, error);
- }
- MonoType*
- ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
- {
- return m_class_get_byval_arg (klass);
- }
- void
- ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array)
- {
- g_ptr_array_free (ptr_array, TRUE);
- }
- void
- ves_icall_Mono_SafeStringMarshal_GFree (void *c_str)
- {
- g_free (c_str);
- }
- char*
- ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoString *volatile* s)
- {
- ERROR_DECL (error);
- char *result = mono_string_to_utf8_checked_internal (*s, error);
- mono_error_set_pending_exception (error);
- return result;
- }
- /* System.TypeCode */
- typedef enum {
- TYPECODE_EMPTY,
- TYPECODE_OBJECT,
- TYPECODE_DBNULL,
- TYPECODE_BOOLEAN,
- TYPECODE_CHAR,
- TYPECODE_SBYTE,
- TYPECODE_BYTE,
- TYPECODE_INT16,
- TYPECODE_UINT16,
- TYPECODE_INT32,
- TYPECODE_UINT32,
- TYPECODE_INT64,
- TYPECODE_UINT64,
- TYPECODE_SINGLE,
- TYPECODE_DOUBLE,
- TYPECODE_DECIMAL,
- TYPECODE_DATETIME,
- TYPECODE_STRING = 18
- } TypeCode;
- #ifndef ENABLE_NETCORE
- guint32
- ves_icall_type_GetTypeCodeInternal (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- if (type->byref)
- return TYPECODE_OBJECT;
- handle_enum:
- switch (type->type) {
- case MONO_TYPE_VOID:
- return TYPECODE_OBJECT;
- case MONO_TYPE_BOOLEAN:
- return TYPECODE_BOOLEAN;
- case MONO_TYPE_U1:
- return TYPECODE_BYTE;
- case MONO_TYPE_I1:
- return TYPECODE_SBYTE;
- case MONO_TYPE_U2:
- return TYPECODE_UINT16;
- case MONO_TYPE_I2:
- return TYPECODE_INT16;
- case MONO_TYPE_CHAR:
- return TYPECODE_CHAR;
- case MONO_TYPE_PTR:
- case MONO_TYPE_U:
- case MONO_TYPE_I:
- return TYPECODE_OBJECT;
- case MONO_TYPE_U4:
- return TYPECODE_UINT32;
- case MONO_TYPE_I4:
- return TYPECODE_INT32;
- case MONO_TYPE_U8:
- return TYPECODE_UINT64;
- case MONO_TYPE_I8:
- return TYPECODE_INT64;
- case MONO_TYPE_R4:
- return TYPECODE_SINGLE;
- case MONO_TYPE_R8:
- return TYPECODE_DOUBLE;
- case MONO_TYPE_VALUETYPE: {
- MonoClass *klass = type->data.klass;
-
- if (m_class_is_enumtype (klass)) {
- type = mono_class_enum_basetype_internal (klass);
- goto handle_enum;
- } else if (mono_is_corlib_image (m_class_get_image (klass))) {
- if (strcmp (m_class_get_name_space (klass), "System") == 0) {
- if (strcmp (m_class_get_name (klass), "Decimal") == 0)
- return TYPECODE_DECIMAL;
- else if (strcmp (m_class_get_name (klass), "DateTime") == 0)
- return TYPECODE_DATETIME;
- }
- }
- return TYPECODE_OBJECT;
- }
- case MONO_TYPE_STRING:
- return TYPECODE_STRING;
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_VAR:
- case MONO_TYPE_MVAR:
- case MONO_TYPE_TYPEDBYREF:
- return TYPECODE_OBJECT;
- case MONO_TYPE_CLASS:
- {
- MonoClass *klass = type->data.klass;
- if (m_class_get_image (klass) == mono_defaults.corlib && strcmp (m_class_get_name_space (klass), "System") == 0) {
- if (strcmp (m_class_get_name (klass), "DBNull") == 0)
- return TYPECODE_DBNULL;
- }
- }
- return TYPECODE_OBJECT;
- case MONO_TYPE_GENERICINST:
- if (m_class_is_enumtype (type->data.generic_class->container_class)) {
- type = mono_class_enum_basetype_internal (type->data.generic_class->container_class);
- goto handle_enum;
- }
- return TYPECODE_OBJECT;
- default:
- g_error ("type 0x%02x not handled in GetTypeCode()", type->type);
- }
- return 0;
- }
- #endif
- guint32
- ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionTypeHandle ref_type, MonoReflectionTypeHandle ref_c, MonoError *error)
- {
- g_assert (!MONO_HANDLE_IS_NULL (ref_type));
-
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- MonoType *ctype = MONO_HANDLE_GETVAL (ref_c, type);
- MonoClass *klassc = mono_class_from_mono_type_internal (ctype);
- if (type->byref ^ ctype->byref)
- return FALSE;
- if (type->byref) {
- return mono_byref_type_is_assignable_from (type, ctype, FALSE);
- }
- gboolean result;
- mono_class_is_assignable_from_checked (klass, klassc, &result, error);
- return (guint32)result;
- }
- MonoBoolean
- ves_icall_RuntimeTypeHandle_is_subclass_of (MonoType *childType, MonoType *baseType)
- {
- ERROR_DECL (error);
- mono_bool result = FALSE;
- MonoClass *childClass;
- MonoClass *baseClass;
- childClass = mono_class_from_mono_type_internal (childType);
- baseClass = mono_class_from_mono_type_internal (baseType);
- if (G_UNLIKELY (childType->byref)) {
- result = !baseType->byref && baseClass == mono_defaults.object_class;
- goto done;
- }
- if (G_UNLIKELY (baseType->byref)) {
- result = FALSE;
- goto done;
- }
- if (childType == baseType) {
- /* .NET IsSubclassOf is not reflexive */
- result = FALSE;
- goto done;
- }
- if (G_UNLIKELY (is_generic_parameter (childType))) {
- /* slow path: walk the type hierarchy looking at base types
- * until we see baseType. If the current type is not a gparam,
- * break out of the loop and use is_subclass_of.
- */
- MonoClass *c = mono_generic_param_get_base_type (childClass);
- result = FALSE;
- while (c != NULL) {
- if (c == baseClass) {
- result = TRUE;
- break;
- }
- if (!is_generic_parameter (m_class_get_byval_arg (c))) {
- result = mono_class_is_subclass_of_internal (c, baseClass, FALSE);
- break;
- } else
- c = mono_generic_param_get_base_type (c);
- }
- } else {
- result = mono_class_is_subclass_of_internal (childClass, baseClass, FALSE);
- }
- done:
- mono_error_set_pending_exception (error);
- return result;
- }
- guint32
- ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionTypeHandle ref_type, MonoObjectHandle obj, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- mono_class_init_checked (klass, error);
- return_val_if_nok (error, FALSE);
- MonoObjectHandle inst = mono_object_handle_isinst (obj, klass, error);
- return_val_if_nok (error, FALSE);
- return !MONO_HANDLE_IS_NULL (inst);
- }
- guint32
- ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- #ifdef ENABLE_NETCORE
- if (type->byref || type->type == MONO_TYPE_PTR || type->type == MONO_TYPE_FNPTR)
- return TYPE_ATTRIBUTE_NOT_PUBLIC;
- #endif
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- return mono_class_get_flags (klass);
- }
- MonoReflectionMarshalAsAttributeHandle
- ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionFieldHandle field_h, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (field_h);
- MonoClassField *field = MONO_HANDLE_GETVAL (field_h, field);
- MonoClass *klass = field->parent;
- MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
- if (mono_class_is_gtd (klass) ||
- (gklass && gklass->context.class_inst->is_open))
- return MONO_HANDLE_CAST (MonoReflectionMarshalAsAttribute, NULL_HANDLE);
- MonoType *ftype = mono_field_get_type_internal (field);
- if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
- return MONO_HANDLE_CAST (MonoReflectionMarshalAsAttribute, NULL_HANDLE);
- MonoMarshalType *info = mono_marshal_load_type_info (klass);
- for (int i = 0; i < info->num_fields; ++i) {
- if (info->fields [i].field == field) {
- if (!info->fields [i].mspec)
- return MONO_HANDLE_CAST (MonoReflectionMarshalAsAttribute, NULL_HANDLE);
- else {
- return mono_reflection_marshal_as_attribute_from_marshal_spec (domain, klass, info->fields [i].mspec, error);
- }
- }
- }
- return MONO_HANDLE_CAST (MonoReflectionMarshalAsAttribute, NULL_HANDLE);
- }
- MonoReflectionFieldHandle
- ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type, MonoError *error)
- {
- MonoClass *klass;
- g_assert (handle);
- if (!type) {
- klass = handle->parent;
- } else {
- klass = mono_class_from_mono_type_internal (type);
- gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
- if (!found)
- /* The managed code will throw the exception */
- return MONO_HANDLE_CAST (MonoReflectionField, NULL_HANDLE);
- }
- return mono_field_get_object_handle (mono_domain_get (), klass, handle, error);
- }
- MonoReflectionEventHandle
- ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type, MonoError *error)
- {
- MonoClass *klass;
- g_assert (handle);
- if (!type) {
- klass = handle->parent;
- } else {
- klass = mono_class_from_mono_type_internal (type);
- gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
- if (!found)
- /* Managed code will throw an exception */
- return MONO_HANDLE_CAST (MonoReflectionEvent, NULL_HANDLE);
- }
- return mono_event_get_object_handle (mono_domain_get (), klass, handle, error);
- }
- MonoReflectionPropertyHandle
- ves_icall_System_Reflection_RuntimePropertyInfo_internal_from_handle_type (MonoProperty *handle, MonoType *type, MonoError *error)
- {
- MonoClass *klass;
- g_assert (handle);
- if (!type) {
- klass = handle->parent;
- } else {
- klass = mono_class_from_mono_type_internal (type);
- gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
- if (!found)
- /* Managed code will throw an exception */
- return MONO_HANDLE_CAST (MonoReflectionProperty, NULL_HANDLE);
- }
- return mono_property_get_object_handle (mono_domain_get (), klass, handle, error);
- }
- MonoArrayHandle
- ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionFieldHandle field_h, MonoBoolean optional, MonoError *error)
- {
- MonoClassField *field = MONO_HANDLE_GETVAL (field_h, field);
- MonoType *type = mono_field_get_type_checked (field, error);
- return_val_if_nok (error, NULL_HANDLE_ARRAY);
- return type_array_from_modifiers (type, optional, error);
- }
- int
- ves_icall_get_method_attributes (MonoMethod *method)
- {
- return method->flags;
- }
- void
- ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info, MonoError *error)
- {
- MonoDomain *domain = mono_domain_get ();
- MonoMethodSignature* sig = mono_method_signature_checked (method, error);
- return_if_nok (error);
- MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, m_class_get_byval_arg (method->klass), error);
- return_if_nok (error);
- MONO_STRUCT_SETREF_INTERNAL (info, parent, MONO_HANDLE_RAW (rt));
- MONO_HANDLE_ASSIGN (rt, mono_type_get_object_handle (domain, sig->ret, error));
- return_if_nok (error);
- MONO_STRUCT_SETREF_INTERNAL (info, ret, MONO_HANDLE_RAW (rt));
- info->attrs = method->flags;
- info->implattrs = method->iflags;
- guint32 callconv;
- if (sig->call_convention == MONO_CALL_DEFAULT)
- callconv = sig->sentinelpos >= 0 ? 2 : 1;
- else {
- if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
- callconv = 2;
- else
- callconv = 1;
- }
- callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
- info->callconv = callconv;
- }
- MonoArrayHandle
- ves_icall_System_Reflection_MonoMethodInfo_get_parameter_info (MonoMethod *method, MonoReflectionMethodHandle member, MonoError *error)
- {
- MonoDomain *domain = mono_domain_get ();
- MonoReflectionTypeHandle reftype = MONO_HANDLE_NEW (MonoReflectionType, NULL);
- MONO_HANDLE_GET (reftype, member, reftype);
- MonoClass *klass = NULL;
- if (!MONO_HANDLE_IS_NULL (reftype))
- klass = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (reftype, type));
- return mono_param_get_objects_internal (domain, method, klass, error);
- }
- MonoReflectionMarshalAsAttributeHandle
- ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method, MonoError *error)
- {
- MonoDomain *domain = mono_domain_get ();
- MonoReflectionMarshalAsAttributeHandle res = MONO_HANDLE_NEW (MonoReflectionMarshalAsAttribute, NULL);
- MonoMarshalSpec **mspecs = g_new (MonoMarshalSpec*, mono_method_signature_internal (method)->param_count + 1);
- mono_method_get_marshal_info (method, mspecs);
- if (mspecs [0]) {
- MONO_HANDLE_ASSIGN (res, mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], error));
- goto_if_nok (error, leave);
- }
-
- leave:
- for (int i = mono_method_signature_internal (method)->param_count; i >= 0; i--)
- if (mspecs [i])
- mono_metadata_free_marshal_spec (mspecs [i]);
- g_free (mspecs);
- return res;
- }
- gint32
- ves_icall_RuntimeFieldInfo_GetFieldOffset (MonoReflectionFieldHandle field, MonoError *error)
- {
- MonoClassField *class_field = MONO_HANDLE_GETVAL (field, field);
- mono_class_setup_fields (class_field->parent);
- return class_field->offset - MONO_ABI_SIZEOF (MonoObject);
- }
- MonoReflectionTypeHandle
- ves_icall_RuntimeFieldInfo_GetParentType (MonoReflectionFieldHandle field, MonoBoolean declaring, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (field);
- MonoClass *parent;
- if (declaring) {
- MonoClassField *f = MONO_HANDLE_GETVAL (field, field);
- parent = f->parent;
- } else {
- parent = MONO_HANDLE_GETVAL (field, klass);
- }
- return mono_type_get_object_handle (domain, m_class_get_byval_arg (parent), error);
- }
- MonoObjectHandle
- ves_icall_RuntimeFieldInfo_GetValueInternal (MonoReflectionFieldHandle field_handle, MonoObjectHandle obj_handle, MonoError *error)
- {
- MonoReflectionField * const field = MONO_HANDLE_RAW (field_handle);
- MonoClass *fklass = field->klass;
- MonoClassField *cf = field->field;
- if (mono_asmctx_get_kind (&m_class_get_image (fklass)->assembly->context) == MONO_ASMCTX_REFONLY) {
- mono_error_set_invalid_operation (error,
- "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods.");
- return NULL_HANDLE;
- }
- if (mono_security_core_clr_enabled () &&
- !mono_security_core_clr_ensure_reflection_access_field (cf, error)) {
- return NULL_HANDLE;
- }
- MonoObject * const obj = MONO_HANDLE_RAW (obj_handle);
- MonoObject *result;
- #ifndef DISABLE_REMOTING
- if (G_UNLIKELY (obj != NULL && mono_class_is_transparent_proxy (mono_object_class (obj)))) {
- /* We get here if someone used a
- * System.Reflection.FieldInfo:GetValue on a
- * ContextBoundObject's or cross-domain MarshalByRefObject's
- * transparent proxy. */
- result = mono_load_remote_field_new_checked (obj, fklass, cf, error);
- } else
- #endif
- result = mono_field_get_value_object_checked (mono_object_domain (field), cf, obj, error);
- return MONO_HANDLE_NEW (MonoObject, result);
- }
- void
- ves_icall_RuntimeFieldInfo_SetValueInternal (MonoReflectionFieldHandle field, MonoObjectHandle obj, MonoObjectHandle value, MonoError *error)
- {
- MonoClassField *cf = MONO_HANDLE_GETVAL (field, field);
- MonoClass *field_klass = MONO_HANDLE_GETVAL (field, klass);
- if (mono_asmctx_get_kind (&m_class_get_image (field_klass)->assembly->context) == MONO_ASMCTX_REFONLY) {
- mono_error_set_invalid_operation (error, "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods.");
- return;
- }
- if (mono_security_core_clr_enabled () &&
- !mono_security_core_clr_ensure_reflection_access_field (cf, error)) {
- return;
- }
- #ifndef DISABLE_REMOTING
- if (G_UNLIKELY (!MONO_HANDLE_IS_NULL (obj) && mono_class_is_transparent_proxy (mono_handle_class (obj)))) {
- /* We get here if someone used a
- * System.Reflection.FieldInfo:SetValue on a
- * ContextBoundObject's or cross-domain MarshalByRefObject's
- * transparent proxy. */
- /* FIXME: use handles for mono_store_remote_field_new_checked */
- MonoObject *v = MONO_HANDLE_RAW (value);
- MonoObject *o = MONO_HANDLE_RAW (obj);
- mono_store_remote_field_new_checked (o, field_klass, cf, v, error);
- return;
- }
- #endif
- MonoType *type = mono_field_get_type_checked (cf, error);
- return_if_nok (error);
- gboolean isref = FALSE;
- MonoGCHandle value_gchandle = 0;
- gchar *v = NULL;
- if (!type->byref) {
- switch (type->type) {
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_U2:
- case MONO_TYPE_I2:
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U:
- case MONO_TYPE_I:
- case MONO_TYPE_U4:
- case MONO_TYPE_I4:
- case MONO_TYPE_R4:
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- case MONO_TYPE_R8:
- case MONO_TYPE_VALUETYPE:
- case MONO_TYPE_PTR:
- isref = FALSE;
- if (!MONO_HANDLE_IS_NULL (value))
- v = (char*)mono_object_handle_pin_unbox (value, &value_gchandle);
- break;
- case MONO_TYPE_STRING:
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_CLASS:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_SZARRAY:
- /* Do nothing */
- isref = TRUE;
- break;
- case MONO_TYPE_GENERICINST: {
- MonoGenericClass *gclass = type->data.generic_class;
- g_assert (!gclass->context.class_inst->is_open);
- if (mono_class_is_nullable (mono_class_from_mono_type_internal (type))) {
- MonoClass *nklass = mono_class_from_mono_type_internal (type);
- /*
- * Convert the boxed vtype into a Nullable structure.
- * This is complicated by the fact that Nullables have
- * a variable structure.
- */
- MonoObjectHandle nullable = mono_object_new_handle (mono_domain_get (), nklass, error);
- return_if_nok (error);
- MonoGCHandle nullable_gchandle = 0;
- guint8 *nval = (guint8*)mono_object_handle_pin_unbox (nullable, &nullable_gchandle);
- mono_nullable_init_from_handle (nval, value, nklass);
- isref = FALSE;
- value_gchandle = nullable_gchandle;
- v = (gchar*)nval;
- }
- else {
- isref = !m_class_is_valuetype (gclass->container_class);
- if (!isref && !MONO_HANDLE_IS_NULL (value)) {
- v = (char*)mono_object_handle_pin_unbox (value, &value_gchandle);
- };
- }
- break;
- }
- default:
- g_error ("type 0x%x not handled in "
- "ves_icall_FieldInfo_SetValueInternal", type->type);
- return;
- }
- }
- /* either value is a reference type, or it's a value type and we pinned
- * it and v points to the payload. */
- g_assert ((isref && v == NULL && value_gchandle == 0) ||
- (!isref && v != NULL && value_gchandle != 0) ||
- (!isref && v == NULL && value_gchandle == 0));
- if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
- MonoVTable *vtable = mono_class_vtable_checked (MONO_HANDLE_DOMAIN (field), cf->parent, error);
- goto_if_nok (error, leave);
- if (!vtable->initialized) {
- if (!mono_runtime_class_init_full (vtable, error))
- goto leave;
- }
- if (isref)
- mono_field_static_set_value_internal (vtable, cf, MONO_HANDLE_RAW (value)); /* FIXME make mono_field_static_set_value work with handles for value */
- else
- mono_field_static_set_value_internal (vtable, cf, v);
- } else {
- if (isref)
- MONO_HANDLE_SET_FIELD_REF (obj, cf, value);
- else
- mono_field_set_value_internal (MONO_HANDLE_RAW (obj), cf, v); /* FIXME: make mono_field_set_value take a handle for obj */
- }
- leave:
- if (value_gchandle)
- mono_gchandle_free_internal (value_gchandle);
- }
- static MonoObjectHandle
- typed_reference_to_object (MonoTypedRef *tref, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- MonoObjectHandle result;
- if (MONO_TYPE_IS_REFERENCE (tref->type)) {
- MonoObject** objp = (MonoObject **)tref->value;
- result = MONO_HANDLE_NEW (MonoObject, *objp);
- } else if (mono_type_is_pointer (tref->type)) {
- /* Boxed as UIntPtr */
- result = mono_value_box_handle (mono_domain_get (), mono_get_uintptr_class (), tref->value, error);
- } else {
- result = mono_value_box_handle (mono_domain_get (), tref->klass, tref->value, error);
- }
- HANDLE_FUNCTION_RETURN_REF (MonoObject, result);
- }
- MonoObjectHandle
- ves_icall_System_RuntimeFieldHandle_GetValueDirect (MonoReflectionFieldHandle field_h, MonoReflectionTypeHandle field_type_h, MonoTypedRef *obj, MonoReflectionTypeHandle context_type_h, MonoError *error)
- {
- MonoClassField *field = MONO_HANDLE_GETVAL (field_h, field);
- MonoClass *klass = mono_class_from_mono_type_internal (field->type);
- if (!MONO_TYPE_ISSTRUCT (m_class_get_byval_arg (field->parent))) {
- mono_error_set_not_implemented (error, "");
- return MONO_HANDLE_NEW (MonoObject, NULL);
- } else if (MONO_TYPE_IS_REFERENCE (field->type)) {
- return MONO_HANDLE_NEW (MonoObject, *(MonoObject**)((guint8*)obj->value + field->offset - sizeof (MonoObject)));
- } else {
- return mono_value_box_handle (mono_domain_get (), klass, (guint8*)obj->value + field->offset - sizeof (MonoObject), error);
- }
- }
- void
- ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionFieldHandle field_h, MonoReflectionTypeHandle field_type_h, MonoTypedRef *obj, MonoObjectHandle value_h, MonoReflectionTypeHandle context_type_h, MonoError *error)
- {
- MonoClassField *f = MONO_HANDLE_GETVAL (field_h, field);
- g_assert (obj);
- mono_class_setup_fields (f->parent);
- if (!MONO_TYPE_ISSTRUCT (m_class_get_byval_arg (f->parent))) {
- MonoObjectHandle objHandle = typed_reference_to_object (obj, error);
- return_if_nok (error);
- ves_icall_RuntimeFieldInfo_SetValueInternal (field_h, objHandle, value_h, error);
- } else if (MONO_TYPE_IS_REFERENCE (f->type)) {
- mono_copy_value (f->type, (guint8*)obj->value + m_field_get_offset (f) - sizeof (MonoObject), MONO_HANDLE_RAW (value_h), FALSE);
- } else {
- MonoGCHandle gchandle = NULL;
- g_assert (MONO_HANDLE_RAW (value_h));
- mono_copy_value (f->type, (guint8*)obj->value + m_field_get_offset (f) - sizeof (MonoObject), mono_object_handle_pin_unbox (value_h, &gchandle), FALSE);
- mono_gchandle_free_internal (gchandle);
- }
- }
- MonoObjectHandle
- ves_icall_RuntimeFieldInfo_GetRawConstantValue (MonoReflectionFieldHandle rfield, MonoError* error)
- {
- MonoObjectHandle o_handle = NULL_HANDLE_INIT;
- MonoObject *o = NULL;
- MonoClassField *field = MONO_HANDLE_GETVAL (rfield, field);
- MonoClass *klass;
- MonoDomain *domain = MONO_HANDLE_DOMAIN (rfield);
- gchar *v;
- MonoTypeEnum def_type;
- const char *def_value;
- MonoType *t;
- MonoStringHandle string_handle = MONO_HANDLE_NEW (MonoString, NULL); // FIXME? Not always needed.
- mono_class_init_internal (field->parent);
- t = mono_field_get_type_checked (field, error);
- goto_if_nok (error, return_null);
- if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
- goto invalid_operation;
- if (image_is_dynamic (m_class_get_image (field->parent))) {
- MonoClass *klass = field->parent;
- int fidx = field - m_class_get_fields (klass);
- MonoFieldDefaultValue *def_values = mono_class_get_field_def_values (klass);
- g_assert (def_values);
- def_type = def_values [fidx].def_type;
- def_value = def_values [fidx].data;
- if (def_type == MONO_TYPE_END)
- goto invalid_operation;
- } else {
- def_value = mono_class_get_field_default_value (field, &def_type);
- /* FIXME, maybe we should try to raise TLE if field->parent is broken */
- if (!def_value)
- goto invalid_operation;
- }
- /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
- switch (def_type) {
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_U2:
- case MONO_TYPE_I2:
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U:
- case MONO_TYPE_I:
- case MONO_TYPE_U4:
- case MONO_TYPE_I4:
- case MONO_TYPE_R4:
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- case MONO_TYPE_R8: {
- MonoType *t;
- /* boxed value type */
- t = g_new0 (MonoType, 1);
- t->type = def_type;
- klass = mono_class_from_mono_type_internal (t);
- g_free (t);
- o = mono_object_new_checked (domain, klass, error);
- goto_if_nok (error, return_null);
- o_handle = MONO_HANDLE_NEW (MonoObject, o);
- v = ((gchar *) o) + sizeof (MonoObject);
- (void)mono_get_constant_value_from_blob (domain, def_type, def_value, v, string_handle, error);
- goto_if_nok (error, return_null);
- break;
- }
- case MONO_TYPE_STRING:
- case MONO_TYPE_CLASS:
- (void)mono_get_constant_value_from_blob (domain, def_type, def_value, &o, string_handle, error);
- goto_if_nok (error, return_null);
- o_handle = MONO_HANDLE_NEW (MonoObject, o);
- break;
- default:
- g_assert_not_reached ();
- }
- goto exit;
- invalid_operation:
- mono_error_set_invalid_operation (error, NULL);
- // fall through
- return_null:
- o_handle = NULL_HANDLE;
- // fall through
- exit:
- return o_handle;
- }
- MonoReflectionTypeHandle
- ves_icall_RuntimeFieldInfo_ResolveType (MonoReflectionFieldHandle ref_field, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_field);
- MonoClassField *field = MONO_HANDLE_GETVAL (ref_field, field);
- MonoType *type = mono_field_get_type_checked (field, error);
- return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
- return mono_type_get_object_handle (domain, type, error);
- }
- void
- ves_icall_RuntimePropertyInfo_get_property_info (MonoReflectionPropertyHandle property, MonoPropertyInfo *info, PInfo req_info, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (property);
- const MonoProperty *pproperty = MONO_HANDLE_GETVAL (property, property);
- if ((req_info & PInfo_ReflectedType) != 0) {
- MonoClass *klass = MONO_HANDLE_GETVAL (property, klass);
- MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
- return_if_nok (error);
- MONO_STRUCT_SETREF_INTERNAL (info, parent, MONO_HANDLE_RAW (rt));
- }
- if ((req_info & PInfo_DeclaringType) != 0) {
- MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, m_class_get_byval_arg (pproperty->parent), error);
- return_if_nok (error);
- MONO_STRUCT_SETREF_INTERNAL (info, declaring_type, MONO_HANDLE_RAW (rt));
- }
- if ((req_info & PInfo_Name) != 0) {
- MonoStringHandle name = mono_string_new_handle (domain, pproperty->name, error);
- return_if_nok (error);
- MONO_STRUCT_SETREF_INTERNAL (info, name, MONO_HANDLE_RAW (name));
- }
- if ((req_info & PInfo_Attributes) != 0)
- info->attrs = pproperty->attrs;
- if ((req_info & PInfo_GetMethod) != 0) {
- MonoClass *property_klass = MONO_HANDLE_GETVAL (property, klass);
- MonoReflectionMethodHandle rm;
- if (pproperty->get &&
- (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
- pproperty->get->klass == property_klass)) {
- rm = mono_method_get_object_handle (domain, pproperty->get, property_klass, error);
- return_if_nok (error);
- } else {
- rm = MONO_HANDLE_NEW (MonoReflectionMethod, NULL);
- }
- MONO_STRUCT_SETREF_INTERNAL (info, get, MONO_HANDLE_RAW (rm));
- }
- if ((req_info & PInfo_SetMethod) != 0) {
- MonoClass *property_klass = MONO_HANDLE_GETVAL (property, klass);
- MonoReflectionMethodHandle rm;
- if (pproperty->set &&
- (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
- pproperty->set->klass == property_klass)) {
- rm = mono_method_get_object_handle (domain, pproperty->set, property_klass, error);
- return_if_nok (error);
- } else {
- rm = MONO_HANDLE_NEW (MonoReflectionMethod, NULL);
- }
- MONO_STRUCT_SETREF_INTERNAL (info, set, MONO_HANDLE_RAW (rm));
- }
- /*
- * There may be other methods defined for properties, though, it seems they are not exposed
- * in the reflection API
- */
- }
- static gboolean
- add_event_other_methods_to_array (MonoDomain *domain, MonoMethod *m, MonoArrayHandle dest, int i, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- error_init (error);
- MonoReflectionMethodHandle rm = mono_method_get_object_handle (domain, m, NULL, error);
- goto_if_nok (error, leave);
- MONO_HANDLE_ARRAY_SETREF (dest, i, rm);
- leave:
- HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
- }
- void
- ves_icall_RuntimeEventInfo_get_event_info (MonoReflectionMonoEventHandle ref_event, MonoEventInfo *info, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_event);
- MonoClass *klass = MONO_HANDLE_GETVAL (ref_event, klass);
- MonoEvent *event = MONO_HANDLE_GETVAL (ref_event, event);
- MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
- return_if_nok (error);
- MONO_STRUCT_SETREF_INTERNAL (info, reflected_type, MONO_HANDLE_RAW (rt));
- rt = mono_type_get_object_handle (domain, m_class_get_byval_arg (event->parent), error);
- return_if_nok (error);
- MONO_STRUCT_SETREF_INTERNAL (info, declaring_type, MONO_HANDLE_RAW (rt));
- MonoStringHandle ev_name = mono_string_new_handle (domain, event->name, error);
- return_if_nok (error);
- MONO_STRUCT_SETREF_INTERNAL (info, name, MONO_HANDLE_RAW (ev_name));
- info->attrs = event->attrs;
- MonoReflectionMethodHandle rm;
- if (event->add) {
- rm = mono_method_get_object_handle (domain, event->add, klass, error);
- return_if_nok (error);
- } else {
- rm = MONO_HANDLE_NEW (MonoReflectionMethod, NULL);
- }
- MONO_STRUCT_SETREF_INTERNAL (info, add_method, MONO_HANDLE_RAW (rm));
- if (event->remove) {
- rm = mono_method_get_object_handle (domain, event->remove, klass, error);
- return_if_nok (error);
- } else {
- rm = MONO_HANDLE_NEW (MonoReflectionMethod, NULL);
- }
- MONO_STRUCT_SETREF_INTERNAL (info, remove_method, MONO_HANDLE_RAW (rm));
- if (event->raise) {
- rm = mono_method_get_object_handle (domain, event->raise, klass, error);
- return_if_nok (error);
- } else {
- rm = MONO_HANDLE_NEW (MonoReflectionMethod, NULL);
- }
- MONO_STRUCT_SETREF_INTERNAL (info, raise_method, MONO_HANDLE_RAW (rm));
- #ifndef MONO_SMALL_CONFIG
- if (event->other) {
- int i, n = 0;
- while (event->other [n])
- n++;
- MonoArrayHandle info_arr = mono_array_new_handle (domain, mono_defaults.method_info_class, n, error);
- return_if_nok (error);
- MONO_STRUCT_SETREF_INTERNAL (info, other_methods, MONO_HANDLE_RAW (info_arr));
- for (i = 0; i < n; i++)
- if (!add_event_other_methods_to_array (domain, event->other [i], info_arr, i, error))
- return;
- }
- #endif
- }
- static void
- collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
- {
- int i;
- MonoClass *ic;
- mono_class_setup_interfaces (klass, error);
- return_if_nok (error);
- int klass_interface_count = m_class_get_interface_count (klass);
- MonoClass **klass_interfaces = m_class_get_interfaces (klass);
- for (i = 0; i < klass_interface_count; i++) {
- ic = klass_interfaces [i];
- g_hash_table_insert (ifaces, ic, ic);
- collect_interfaces (ic, ifaces, error);
- return_if_nok (error);
- }
- }
- typedef struct {
- MonoArrayHandle iface_array;
- MonoGenericContext *context;
- MonoError *error;
- MonoDomain *domain;
- int next_idx;
- } FillIfaceArrayData;
- static void
- fill_iface_array (gpointer key, gpointer value, gpointer user_data)
- {
- HANDLE_FUNCTION_ENTER ();
- FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
- MonoClass *ic = (MonoClass *)key;
- MonoType *ret = m_class_get_byval_arg (ic), *inflated = NULL;
- MonoError *error = data->error;
- goto_if_nok (error, leave);
- if (data->context && mono_class_is_ginst (ic) && mono_class_get_generic_class (ic)->context.class_inst->is_open) {
- inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, error);
- goto_if_nok (error, leave);
- }
- MonoReflectionTypeHandle rt;
- rt = mono_type_get_object_handle (data->domain, ret, error);
- goto_if_nok (error, leave);
- MONO_HANDLE_ARRAY_SETREF (data->iface_array, data->next_idx, rt);
- data->next_idx++;
- if (inflated)
- mono_metadata_free_type (inflated);
- leave:
- HANDLE_FUNCTION_RETURN ();
- }
- static guint
- get_interfaces_hash (gconstpointer v1)
- {
- MonoClass *k = (MonoClass*)v1;
- return m_class_get_type_token (k);
- }
- MonoArrayHandle
- ves_icall_RuntimeType_GetInterfaces (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
- MonoGenericContext *context = NULL;
- if (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst->is_open) {
- context = mono_class_get_context (klass);
- klass = mono_class_get_generic_class (klass)->container_class;
- }
- for (MonoClass *parent = klass; parent; parent = m_class_get_parent (parent)) {
- mono_class_setup_interfaces (parent, error);
- goto_if_nok (error, fail);
- collect_interfaces (parent, iface_hash, error);
- goto_if_nok (error, fail);
- }
- MonoDomain *domain;
- domain = MONO_HANDLE_DOMAIN (ref_type);
- int len;
- len = g_hash_table_size (iface_hash);
- if (len == 0) {
- g_hash_table_destroy (iface_hash);
- if (!domain->empty_types) {
- domain->empty_types = mono_array_new_cached (domain, mono_defaults.runtimetype_class, 0, error);
- mono_gc_wbarrier_generic_nostore_internal (&domain->empty_types);
- goto_if_nok (error, fail);
- }
- return MONO_HANDLE_NEW (MonoArray, domain->empty_types);
- }
- FillIfaceArrayData data;
- data.iface_array = MONO_HANDLE_NEW (MonoArray, mono_array_new_cached (domain, mono_defaults.runtimetype_class, len, error));
- goto_if_nok (error, fail);
- data.context = context;
- data.error = error;
- data.domain = domain;
- data.next_idx = 0;
- g_hash_table_foreach (iface_hash, fill_iface_array, &data);
- goto_if_nok (error, fail);
- g_hash_table_destroy (iface_hash);
- return data.iface_array;
- fail:
- g_hash_table_destroy (iface_hash);
- return NULL_HANDLE_ARRAY;
- }
- static gboolean
- method_is_reabstracted (MonoMethod *method)
- {
- /* only on interfaces */
- /* method is marked "final abstract" */
- /* FIXME: we need some other way to detect reabstracted methods. "final" is an incidental detail of the spec. */
- return m_method_is_final (method) && m_method_is_abstract (method);
- }
- static gboolean
- method_is_dim (MonoMethod *method)
- {
- /* only valid on interface methods*/
- /* method is marked "virtual" but not "virtual abstract" */
- return m_method_is_virtual (method) && !m_method_is_abstract (method);
- }
- static gboolean
- set_interface_map_data_method_object (MonoDomain *domain, MonoMethod *method, MonoClass *iclass, int ioffset, MonoClass *klass, MonoArrayHandle targets, MonoArrayHandle methods, int i, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- error_init (error);
- MonoReflectionMethodHandle member = mono_method_get_object_handle (domain, method, iclass, error);
- goto_if_nok (error, leave);
- MONO_HANDLE_ARRAY_SETREF (methods, i, member);
- MonoMethod* foundMethod = m_class_get_vtable (klass) [i + ioffset];
- if (mono_class_has_dim_conflicts (klass) && mono_class_is_interface (foundMethod->klass)) {
- GSList* conflicts = mono_class_get_dim_conflicts (klass);
- GSList* l;
- MonoMethod* decl = method;
- if (decl->is_inflated)
- decl = ((MonoMethodInflated*)decl)->declaring;
- gboolean in_conflict = FALSE;
- for (l = conflicts; l; l = l->next) {
- if (decl == l->data) {
- in_conflict = TRUE;
- break;
- }
- }
- if (in_conflict) {
- MONO_HANDLE_ARRAY_SETREF (targets, i, NULL_HANDLE);
- goto leave;
- }
- }
- /*
- * if the iterface method is reabstracted, and either the found implementation method is abstract, or the found
- * implementation method is from another DIM (meaning neither klass nor any of its ancestor classes implemented
- * the method), then say the target method is null.
- */
- if (method_is_reabstracted (method) &&
- (m_method_is_abstract (foundMethod) ||
- (mono_class_is_interface (foundMethod->klass) && method_is_dim (foundMethod))))
- MONO_HANDLE_ARRAY_SETREF (targets, i, NULL_HANDLE);
- else if (mono_class_is_interface (foundMethod->klass) && method_is_reabstracted (foundMethod) && !m_class_is_abstract (klass)) {
- /* if the method we found is a reabstracted DIM method, but the class isn't abstract, return NULL */
- /*
- * (C# doesn't seem to allow constructing such types, it requires the whole class to be abstract - in
- * which case we are supposed to return the reabstracted interface method. But in IL we can make a
- * non-abstract class with reabstracted interface methods - which is supposed to fail with an
- * EntryPointNotFoundException at invoke time, but does not prevent the class from loading.)
- */
- MONO_HANDLE_ARRAY_SETREF (targets, i, NULL_HANDLE);
- } else {
- MONO_HANDLE_ASSIGN (member, mono_method_get_object_handle (domain, foundMethod, mono_class_is_interface (foundMethod->klass) ? foundMethod->klass : klass, error));
- goto_if_nok (error, leave);
- MONO_HANDLE_ARRAY_SETREF (targets, i, member);
- }
-
- leave:
- HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
- }
- void
- ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionTypeHandle ref_type, MonoReflectionTypeHandle ref_iface, MonoArrayHandleOut targets, MonoArrayHandleOut methods, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- MonoType *iface = MONO_HANDLE_GETVAL (ref_iface, type);
- MonoClass *iclass = mono_class_from_mono_type_internal (iface);
- mono_class_init_checked (klass, error);
- return_if_nok (error);
- mono_class_init_checked (iclass, error);
- return_if_nok (error);
- mono_class_setup_vtable (klass);
- gboolean variance_used;
- int ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
- if (ioffset == -1)
- return;
- MonoMethod* method;
- int i = 0;
- gpointer iter = NULL;
- MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
- while ((method = mono_class_get_methods(iclass, &iter))) {
- if (method->flags & METHOD_ATTRIBUTE_VIRTUAL)
- i++;
- }
-
- MonoArrayHandle targets_arr = mono_array_new_handle (domain, mono_defaults.method_info_class, i, error);
- return_if_nok (error);
- MONO_HANDLE_ASSIGN (targets, targets_arr);
- MonoArrayHandle methods_arr = mono_array_new_handle (domain, mono_defaults.method_info_class, i, error);
- return_if_nok (error);
- MONO_HANDLE_ASSIGN (methods, methods_arr);
- i = 0;
- iter = NULL;
- while ((method = mono_class_get_methods (iclass, &iter))) {
- if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL))
- continue;
- if (!set_interface_map_data_method_object (domain, method, iclass, ioffset, klass, targets, methods, i, error))
- return;
- i ++;
- }
- }
- void
- ves_icall_RuntimeType_GetPacking (MonoReflectionTypeHandle ref_type, guint32 *packing, guint32 *size, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- mono_class_init_checked (klass, error);
- return_if_nok (error);
- if (image_is_dynamic (m_class_get_image (klass))) {
- MonoReflectionTypeBuilderHandle tb = MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_type);
- *packing = MONO_HANDLE_GETVAL (tb, packing_size);
- *size = MONO_HANDLE_GETVAL (tb, class_size);
- } else {
- mono_metadata_packing_from_typedef (m_class_get_image (klass), m_class_get_type_token (klass), packing, size);
- }
- }
- MonoReflectionTypeHandle
- ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- if (!type->byref && type->type == MONO_TYPE_SZARRAY) {
- return mono_type_get_object_handle (domain, m_class_get_byval_arg (type->data.klass), error);
- }
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- mono_class_init_checked (klass, error);
- return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
- // GetElementType should only return a type for:
- // Array Pointer PassedByRef
- if (type->byref)
- return mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
- else if (m_class_get_element_class (klass) && MONO_CLASS_IS_ARRAY (klass))
- return mono_type_get_object_handle (domain, m_class_get_byval_arg (m_class_get_element_class (klass)), error);
- else if (m_class_get_element_class (klass) && type->type == MONO_TYPE_PTR)
- return mono_type_get_object_handle (domain, m_class_get_byval_arg (m_class_get_element_class (klass)), error);
- else
- return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
- }
- MonoReflectionTypeHandle
- ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- if (type->byref)
- return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- if (!m_class_get_parent (klass))
- return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
- return mono_type_get_object_handle (domain, m_class_get_byval_arg (m_class_get_parent (klass)), error);
- }
- guint32
- ves_icall_RuntimeTypeHandle_GetCorElementType (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- if (type->byref)
- return MONO_TYPE_BYREF;
- else
- return (guint32)type->type;
- }
- MonoBoolean
- ves_icall_RuntimeTypeHandle_HasReferences (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- MonoClass *klass;
- klass = mono_class_from_mono_type_internal (type);
- mono_class_init_internal (klass);
- return m_class_has_references (klass);
- }
- MonoBoolean
- ves_icall_RuntimeTypeHandle_IsByRefLike (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- /* .NET Core says byref types are not IsByRefLike */
- if (type->byref)
- return FALSE;
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- return m_class_is_byreflike (klass);
- }
- MonoBoolean
- ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- mono_class_init_checked (klass, error);
- return_val_if_nok (error, FALSE);
- return mono_class_is_com_object (klass);
- }
- guint32
- ves_icall_reflection_get_token (MonoObjectHandle obj, MonoError *error)
- {
- error_init (error);
- return mono_reflection_get_token_checked (obj, error);
- }
- MonoReflectionModuleHandle
- ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionTypeHandle type, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (type);
- MonoType *t = MONO_HANDLE_GETVAL (type, type);
- MonoClass *klass = mono_class_from_mono_type_internal (t);
- return mono_module_get_object_handle (domain, m_class_get_image (klass), error);
- }
- MonoReflectionAssemblyHandle
- ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionTypeHandle type, MonoError *error)
- {
- MonoDomain *domain = mono_domain_get ();
- MonoType *t = MONO_HANDLE_GETVAL (type, type);
- MonoClass *klass = mono_class_from_mono_type_internal (t);
- return mono_assembly_get_object_handle (domain, m_class_get_image (klass)->assembly, error);
- }
- MonoReflectionTypeHandle
- ves_icall_RuntimeType_get_DeclaringType (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- MonoDomain *domain = mono_domain_get ();
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- MonoClass *klass;
- if (type->byref)
- return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
- if (type->type == MONO_TYPE_VAR) {
- MonoGenericContainer *param = mono_type_get_generic_param_owner (type);
- klass = param ? param->owner.klass : NULL;
- } else if (type->type == MONO_TYPE_MVAR) {
- MonoGenericContainer *param = mono_type_get_generic_param_owner (type);
- klass = param ? param->owner.method->klass : NULL;
- } else {
- klass = m_class_get_nested_in (mono_class_from_mono_type_internal (type));
- }
- if (!klass)
- return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
- return mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
- }
- MonoStringHandle
- ves_icall_RuntimeType_get_Name (MonoReflectionTypeHandle reftype, MonoError *error)
- {
- MonoDomain *domain = mono_domain_get ();
- MonoType *type = MONO_HANDLE_RAW(reftype)->type;
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- // FIXME: this should be escaped in some scenarios with mono_identifier_escape_type_name_chars
- // Determining exactly when to do so is fairly difficult, so for now we don't bother to avoid regressions
- const char *klass_name = m_class_get_name (klass);
- if (type->byref) {
- char *n = g_strdup_printf ("%s&", klass_name);
- MonoStringHandle res = mono_string_new_handle (domain, n, error);
- g_free (n);
- return res;
- } else {
- return mono_string_new_handle (domain, klass_name, error);
- }
- }
- MonoStringHandle
- ves_icall_RuntimeType_get_Namespace (MonoReflectionTypeHandle type, MonoError *error)
- {
- MonoDomain *domain = mono_domain_get ();
- MonoClass *klass = mono_class_from_mono_type_handle (type);
- MonoClass *klass_nested_in;
- while ((klass_nested_in = m_class_get_nested_in (klass)))
- klass = klass_nested_in;
- if (m_class_get_name_space (klass) [0] == '\0')
- return NULL_HANDLE_STRING;
- char *escaped = mono_identifier_escape_type_name_chars (m_class_get_name_space (klass));
- MonoStringHandle res = mono_string_new_handle (domain, escaped, error);
- g_free (escaped);
- return res;
- }
- gint32
- ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- error_init (error);
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- if (type->type != MONO_TYPE_ARRAY && type->type != MONO_TYPE_SZARRAY) {
- mono_error_set_argument (error, "type", "Type must be an array type");
- return 0;
- }
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- return m_class_get_rank (klass);
- }
- static MonoArrayHandle
- create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
- {
- return mono_array_new_handle (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
- }
- static gboolean
- set_type_object_in_array (MonoDomain *domain, MonoType *type, MonoArrayHandle dest, int i, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER();
- error_init (error);
- MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, type, error);
- goto_if_nok (error, leave);
- MONO_HANDLE_ARRAY_SETREF (dest, i, rt);
- leave:
- HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
- }
- #ifndef ENABLE_NETCORE
- void
- ves_icall_RuntimeType_GetGUID (MonoReflectionTypeHandle type_handle, MonoArrayHandle guid_handle, MonoError *error)
- {
- error_init (error);
- g_assert (mono_array_handle_length (guid_handle) == 16);
- if (MONO_HANDLE_IS_NULL (type_handle)) {
- mono_error_set_argument_null (error, "type", "");
- return;
- }
- MonoType *type = MONO_HANDLE_GETVAL (type_handle, type);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- if (!mono_class_init_checked (klass, error))
- return;
- guint8 *data = (guint8*) mono_array_addr_with_size_internal (MONO_HANDLE_RAW (guid_handle), 1, 0);
- mono_metadata_get_class_guid (klass, data, error);
- }
- #endif
- MonoArrayHandle
- ves_icall_RuntimeType_GetGenericArguments (MonoReflectionTypeHandle ref_type, MonoBoolean runtimeTypeArray, MonoError *error)
- {
- error_init (error);
- MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- MonoArrayHandle res = MONO_HANDLE_NEW (MonoArray, NULL);
- if (mono_class_is_gtd (klass)) {
- MonoGenericContainer *container = mono_class_get_generic_container (klass);
- MONO_HANDLE_ASSIGN (res, create_type_array (domain, runtimeTypeArray, container->type_argc, error));
- goto_if_nok (error, leave);
- for (int i = 0; i < container->type_argc; ++i) {
- MonoClass *pklass = mono_class_create_generic_parameter (mono_generic_container_get_param (container, i));
- if (!set_type_object_in_array (domain, m_class_get_byval_arg (pklass), res, i, error))
- goto leave;
- }
-
- } else if (mono_class_is_ginst (klass)) {
- MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
- MONO_HANDLE_ASSIGN (res, create_type_array (domain, runtimeTypeArray, inst->type_argc, error));
- goto_if_nok (error, leave);
- for (int i = 0; i < inst->type_argc; ++i) {
- if (!set_type_object_in_array (domain, inst->type_argv [i], res, i, error))
- goto leave;
- }
- }
- leave:
- return res;
- }
- MonoBoolean
- ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- error_init (error);
- if (!IS_MONOTYPE (MONO_HANDLE_RAW(ref_type)))
- return FALSE;
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- if (type->byref)
- return FALSE;
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- return mono_class_is_gtd (klass);
- }
- MonoReflectionTypeHandle
- ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- error_init (error);
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- MonoReflectionTypeHandle ret = MONO_HANDLE_NEW (MonoReflectionType, NULL);
- if (type->byref)
- goto leave;
- MonoClass *klass;
- klass = mono_class_from_mono_type_internal (type);
- if (mono_class_is_gtd (klass)) {
- /* check this one */
- MONO_HANDLE_ASSIGN (ret, ref_type);
- goto leave;
- }
- if (mono_class_is_ginst (klass)) {
- MonoClass *generic_class = mono_class_get_generic_class (klass)->container_class;
- MonoGCHandle ref_info_handle = mono_class_get_ref_info_handle (generic_class);
-
- if (m_class_was_typebuilder (generic_class) && ref_info_handle) {
- MonoObjectHandle tb = mono_gchandle_get_target_handle (ref_info_handle);
- g_assert (!MONO_HANDLE_IS_NULL (tb));
- MONO_HANDLE_ASSIGN (ret, tb);
- } else {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
- MONO_HANDLE_ASSIGN (ret, mono_type_get_object_handle (domain, m_class_get_byval_arg (generic_class), error));
- }
- }
- leave:
- return ret;
- }
- MonoReflectionTypeHandle
- ves_icall_RuntimeType_MakeGenericType (MonoReflectionTypeHandle reftype, MonoArrayHandle type_array, MonoError *error)
- {
- error_init (error);
- MonoDomain *domain = MONO_HANDLE_DOMAIN (reftype);
- g_assert (IS_MONOTYPE_HANDLE (reftype));
- MonoType *type = MONO_HANDLE_GETVAL (reftype, type);
- mono_class_init_checked (mono_class_from_mono_type_internal (type), error);
- return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
- int count = mono_array_handle_length (type_array);
- MonoType **types = g_new0 (MonoType *, count);
- MonoReflectionTypeHandle t = MONO_HANDLE_NEW (MonoReflectionType, NULL);
- for (int i = 0; i < count; i++) {
- MONO_HANDLE_ARRAY_GETREF (t, type_array, i);
- types [i] = MONO_HANDLE_GETVAL (t, type);
- }
- MonoType *geninst = mono_reflection_bind_generic_parameters (reftype, count, types, error);
- g_free (types);
- if (!geninst) {
- return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
- }
- MonoClass *klass = mono_class_from_mono_type_internal (geninst);
- /*we might inflate to the GTD*/
- if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
- mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
- return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
- }
- return mono_type_get_object_handle (domain, geninst, error);
- }
- MonoBoolean
- ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- error_init (error);
- MonoClass *klass;
- if (!IS_MONOTYPE (MONO_HANDLE_RAW (ref_type)))
- return FALSE;
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- if (type->byref)
- return FALSE;
- klass = mono_class_from_mono_type_internal (type);
- return mono_class_is_ginst (klass) || mono_class_is_gtd (klass);
- }
- gint32
- ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- error_init (error);
- if (!IS_MONOTYPE_HANDLE (ref_type))
- return -1;
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- if (is_generic_parameter (type))
- return mono_type_get_generic_param_num (type);
- return -1;
- }
- MonoGenericParamInfo *
- ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- error_init (error);
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- return mono_generic_param_info (type->data.generic_param);
- }
- MonoBoolean
- ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL(ref_type, type);
- return is_generic_parameter (type);
- }
- MonoReflectionMethodHandle
- ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionTypeHandle ref_type,
- MonoReflectionMethodHandle generic,
- MonoError *error)
- {
- error_init (error);
- MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
-
- mono_class_init_checked (klass, error);
- return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE));
- MonoMethod *generic_method = MONO_HANDLE_GETVAL (generic, method);
-
- MonoReflectionMethodHandle ret = MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
- MonoMethod *method;
- gpointer iter = NULL;
- while ((method = mono_class_get_methods (klass, &iter))) {
- if (method->token == generic_method->token) {
- ret = mono_method_get_object_handle (domain, method, klass, error);
- return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE));
- }
- }
- return ret;
- }
- MonoReflectionMethodHandle
- ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- error_init (error);
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- MonoReflectionMethodHandle ret = MONO_HANDLE_NEW (MonoReflectionMethod, NULL);
- if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
- mono_error_set_invalid_operation (error, "DeclaringMethod can only be used on generic arguments");
- goto leave;
- }
- if (type->type == MONO_TYPE_VAR)
- goto leave;
- MonoMethod *method;
- method = mono_type_get_generic_param_owner (type)->owner.method;
- g_assert (method);
- MonoDomain *domain;
- domain = MONO_HANDLE_DOMAIN (ref_type);
- MONO_HANDLE_ASSIGN (ret, mono_method_get_object_handle (domain, method, method->klass, error));
- leave:
- return ret;
- }
- #ifndef ENABLE_NETCORE
- MonoBoolean
- ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (MonoError *error)
- {
- error_init (error);
- mono_error_set_not_implemented (error, "%s", "System.RuntimeType.IsTypeExportedToWindowsRuntime");
- return FALSE;
- }
- MonoBoolean
- ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (MonoError *error)
- {
- error_init (error);
- mono_error_set_not_implemented (error, "%s", "System.RuntimeType.IsWindowsRuntimeObjectType");
- return FALSE;
- }
- #endif /* ENABLE_NETCORE */
- void
- ves_icall_RuntimeMethodInfo_GetPInvoke (MonoReflectionMethodHandle ref_method, int* flags, MonoStringHandleOut entry_point, MonoStringHandleOut dll_name, MonoError *error)
- {
- MonoDomain *domain = mono_domain_get ();
- MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
- MonoImage *image = m_class_get_image (method->klass);
- MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
- MonoTableInfo *tables = image->tables;
- MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
- MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
- guint32 im_cols [MONO_IMPLMAP_SIZE];
- guint32 scope_token;
- const char *import = NULL;
- const char *scope = NULL;
- error_init (error);
- if (image_is_dynamic (image)) {
- MonoReflectionMethodAux *method_aux =
- (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method);
- if (method_aux) {
- import = method_aux->dllentry;
- scope = method_aux->dll;
- }
- if (!import || !scope) {
- mono_error_set_argument (error, "method", "System.Refleciton.Emit method with invalid pinvoke information");
- return;
- }
- }
- else {
- if (piinfo->implmap_idx) {
- mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
-
- piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
- import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
- scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
- scope = mono_metadata_string_heap (image, scope_token);
- }
- }
-
- *flags = piinfo->piflags;
- MONO_HANDLE_ASSIGN (entry_point, mono_string_new_handle (domain, import, error));
- return_if_nok (error);
- MONO_HANDLE_ASSIGN (dll_name, mono_string_new_handle (domain, scope, error));
- }
- MonoReflectionMethodHandle
- ves_icall_RuntimeMethodInfo_GetGenericMethodDefinition (MonoReflectionMethodHandle ref_method, MonoError *error)
- {
- error_init (error);
- MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
- if (method->is_generic)
- return ref_method;
- if (!method->is_inflated)
- return MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
- MonoMethodInflated *imethod = (MonoMethodInflated *) method;
- MonoMethod *result = imethod->declaring;
- /* Not a generic method. */
- if (!result->is_generic)
- return MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
- if (image_is_dynamic (m_class_get_image (method->klass))) {
- MonoDynamicImage *image = (MonoDynamicImage*)m_class_get_image (method->klass);
- /*
- * FIXME: Why is this stuff needed at all ? Why can't the code below work for
- * the dynamic case as well ?
- */
- mono_image_lock ((MonoImage*)image);
- MonoReflectionMethodHandle res = MONO_HANDLE_NEW (MonoReflectionMethod, (MonoReflectionMethod*)mono_g_hash_table_lookup (image->generic_def_objects, imethod));
- mono_image_unlock ((MonoImage*)image);
- if (!MONO_HANDLE_IS_NULL (res))
- return res;
- }
- if (imethod->context.class_inst) {
- MonoClass *klass = ((MonoMethod *) imethod)->klass;
- /*Generic methods gets the context of the GTD.*/
- if (mono_class_get_context (klass)) {
- result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), error);
- return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE));
- }
- }
- return mono_method_get_object_handle (MONO_HANDLE_DOMAIN (ref_method), result, NULL, error);
- }
- #ifdef ENABLE_NETCORE
- static GENERATE_TRY_GET_CLASS_WITH_CACHE (stream, "System.IO", "Stream")
- static int io_stream_begin_read_slot = -1;
- static int io_stream_begin_write_slot = -1;
- static int io_stream_end_read_slot = -1;
- static int io_stream_end_write_slot = -1;
- static gboolean io_stream_slots_set = FALSE;
- static void
- init_io_stream_slots (void)
- {
- MonoClass* klass = mono_class_try_get_stream_class ();
- mono_class_setup_vtable (klass);
- MonoMethod **klass_methods = m_class_get_methods (klass);
- if (!klass_methods) {
- mono_class_setup_methods (klass);
- klass_methods = m_class_get_methods (klass);
- }
- int method_count = mono_class_get_method_count (klass);
- int methods_found = 0;
- for (int i = 0; i < method_count; i++) {
- // find slots for Begin(End)Read and Begin(End)Write
- MonoMethod* m = klass_methods [i];
- if (m->slot == -1)
- continue;
- if (!strcmp (m->name, "BeginRead")) {
- methods_found++;
- io_stream_begin_read_slot = m->slot;
- } else if (!strcmp (m->name, "BeginWrite")) {
- methods_found++;
- io_stream_begin_write_slot = m->slot;
- } else if (!strcmp (m->name, "EndRead")) {
- methods_found++;
- io_stream_end_read_slot = m->slot;
- } else if (!strcmp (m->name, "EndWrite")) {
- methods_found++;
- io_stream_end_write_slot = m->slot;
- }
- }
- g_assert (methods_found <= 4); // some of them can be linked out
- io_stream_slots_set = TRUE;
- }
- MonoBoolean
- ves_icall_System_IO_Stream_HasOverriddenBeginEndRead (MonoObjectHandle stream, MonoError *error)
- {
- MonoClass* curr_klass = MONO_HANDLE_GET_CLASS (stream);
- MonoClass* base_klass = mono_class_try_get_stream_class ();
- if (!io_stream_slots_set)
- init_io_stream_slots ();
- // slots can still be -1 and it means Linker removed the methods from the base class (Stream)
- // in this case we can safely assume the methods are not overridden
- // otherwise - check vtable
- MonoMethod **curr_klass_vtable = m_class_get_vtable (curr_klass);
- gboolean begin_read_is_overriden = io_stream_begin_read_slot != -1 && curr_klass_vtable [io_stream_begin_read_slot]->klass != base_klass;
- gboolean end_read_is_overriden = io_stream_end_read_slot != -1 && curr_klass_vtable [io_stream_end_read_slot]->klass != base_klass;
- // return true if BeginRead or EndRead were overriden
- return begin_read_is_overriden || end_read_is_overriden;
- }
- MonoBoolean
- ves_icall_System_IO_Stream_HasOverriddenBeginEndWrite (MonoObjectHandle stream, MonoError *error)
- {
- MonoClass* curr_klass = MONO_HANDLE_GETVAL (stream, vtable)->klass;
- MonoClass* base_klass = mono_class_try_get_stream_class ();
- if (!io_stream_slots_set)
- init_io_stream_slots ();
- MonoMethod **curr_klass_vtable = m_class_get_vtable (curr_klass);
- gboolean begin_write_is_overriden = curr_klass_vtable [io_stream_begin_write_slot]->klass != base_klass;
- gboolean end_write_is_overriden = curr_klass_vtable [io_stream_end_write_slot]->klass != base_klass;
- // return true if BeginWrite or EndWrite were overriden
- return begin_write_is_overriden || end_write_is_overriden;
- }
- #endif
- MonoBoolean
- ves_icall_RuntimeMethodInfo_get_IsGenericMethod (MonoReflectionMethodHandle ref_method, MonoError *erro)
- {
- MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
- return mono_method_signature_internal (method)->generic_param_count != 0;
- }
- MonoBoolean
- ves_icall_RuntimeMethodInfo_get_IsGenericMethodDefinition (MonoReflectionMethodHandle ref_method, MonoError *Error)
- {
- MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
- return method->is_generic;
- }
- static gboolean
- set_array_generic_argument_handle_inflated (MonoDomain *domain, MonoGenericInst *inst, int i, MonoArrayHandle arr, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- error_init (error);
- MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, inst->type_argv [i], error);
- goto_if_nok (error, leave);
- MONO_HANDLE_ARRAY_SETREF (arr, i, rt);
- leave:
- HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
- }
- static gboolean
- set_array_generic_argument_handle_gparam (MonoDomain *domain, MonoGenericContainer *container, int i, MonoArrayHandle arr, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- error_init (error);
- MonoGenericParam *param = mono_generic_container_get_param (container, i);
- MonoClass *pklass = mono_class_create_generic_parameter (param);
- MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, m_class_get_byval_arg (pklass), error);
- goto_if_nok (error, leave);
- MONO_HANDLE_ARRAY_SETREF (arr, i, rt);
- leave:
- HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
- }
- MonoArrayHandle
- ves_icall_RuntimeMethodInfo_GetGenericArguments (MonoReflectionMethodHandle ref_method, MonoError *error)
- {
- error_init (error);
- MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_method);
- MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
- if (method->is_inflated) {
- MonoGenericInst *inst = mono_method_get_context (method)->method_inst;
- if (inst) {
- int count = inst->type_argc;
- MonoArrayHandle res = mono_array_new_handle (domain, mono_defaults.systemtype_class, count, error);
- return_val_if_nok (error, NULL_HANDLE_ARRAY);
- for (int i = 0; i < count; i++) {
- if (!set_array_generic_argument_handle_inflated (domain, inst, i, res, error))
- break;
- }
- return_val_if_nok (error, NULL_HANDLE_ARRAY);
- return res;
- }
- }
- int count = mono_method_signature_internal (method)->generic_param_count;
- MonoArrayHandle res = mono_array_new_handle (domain, mono_defaults.systemtype_class, count, error);
- return_val_if_nok (error, NULL_HANDLE_ARRAY);
- MonoGenericContainer *container = mono_method_get_generic_container (method);
- for (int i = 0; i < count; i++) {
- if (!set_array_generic_argument_handle_gparam (domain, container, i, res, error))
- break;
- }
- return_val_if_nok (error, NULL_HANDLE_ARRAY);
- return res;
- }
- MonoObjectHandle
- ves_icall_InternalInvoke (MonoReflectionMethodHandle method_handle, MonoObjectHandle this_arg_handle,
- MonoArrayHandle params_handle, MonoExceptionHandleOut exception_out, MonoError *error)
- {
- MonoReflectionMethod* const method = MONO_HANDLE_RAW (method_handle);
- MonoObject* const this_arg = MONO_HANDLE_RAW (this_arg_handle);
- MonoArray* const params = MONO_HANDLE_RAW (params_handle);
- /*
- * Invoke from reflection is supposed to always be a virtual call (the API
- * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
- * greater flexibility.
- */
- MonoMethod *m = method->method;
- MonoMethodSignature* const sig = mono_method_signature_internal (m);
- MonoImage *image = NULL;
- int pcount = 0;
- void *obj = this_arg;
- char *this_name = NULL;
- char *target_name = NULL;
- char *msg = NULL;
- MonoObject *result = NULL;
- MonoArray *arr = NULL;
- MonoException *exception = NULL;
- *MONO_HANDLE_REF (exception_out) = NULL;
- if (mono_security_core_clr_enabled () &&
- !mono_security_core_clr_ensure_reflection_access_method (m, error)) {
- goto return_null;
- }
- if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
- if (!mono_class_vtable_checked (mono_object_domain (method), m->klass, error)) {
- mono_error_cleanup (error); /* FIXME does this make sense? */
- error_init_reuse (error);
- exception = mono_class_get_exception_for_failure (m->klass);
- goto return_null;
- }
- if (this_arg) {
- if (!mono_object_isinst_checked (this_arg, m->klass, error)) {
- if (!is_ok (error)) {
- exception = mono_error_convert_to_exception (error);
- goto return_null;
- }
- this_name = mono_type_get_full_name (mono_object_class (this_arg));
- target_name = mono_type_get_full_name (m->klass);
- msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
- exception = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg);
- goto return_null;
- }
- m = mono_object_get_virtual_method_internal (this_arg, m);
- /* must pass the pointer to the value for valuetype methods */
- if (m_class_is_valuetype (m->klass)) {
- obj = mono_object_unbox_internal (this_arg);
- // FIXMEcoop? Does obj need to be put into a handle?
- }
- } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
- exception = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target.");
- goto return_null;
- }
- }
- if ((m->klass != NULL && m_class_is_byreflike (m->klass)) || m_class_is_byreflike (mono_class_from_mono_type_internal (sig->ret))) {
- exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method with stack pointers via reflection");
- goto return_null;
- }
- #if ENABLE_NETCORE
- if (sig->ret->byref) {
- MonoType* ret_byval = m_class_get_byval_arg (mono_class_from_mono_type_internal (sig->ret));
- if (ret_byval->type == MONO_TYPE_VOID) {
- exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "ByRef to void return values are not supported in reflection invocation");
- goto return_null;
- }
- if (m_class_is_byreflike (mono_class_from_mono_type_internal (ret_byval))) {
- exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method returning ByRef to ByRefLike type via reflection");
- goto return_null;
- }
- }
- #else
- if (sig->ret->byref) {
- exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method returning ByRef type via reflection");
- goto return_null;
- }
- #endif
- pcount = params? mono_array_length_internal (params): 0;
- if (pcount != sig->param_count) {
- exception = mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException");
- goto return_null;
- }
- if (mono_class_is_abstract (m->klass) && !strcmp (m->name, ".ctor") && !this_arg) {
- exception = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class.");
- goto return_null;
- }
- image = m_class_get_image (m->klass);
- if (mono_asmctx_get_kind (&image->assembly->context) == MONO_ASMCTX_REFONLY) {
- exception = mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api.");
- goto return_null;
- }
- if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
- exception = mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access.");
- goto return_null;
- }
-
- if (m_class_get_rank (m->klass) && !strcmp (m->name, ".ctor")) {
- int i;
- pcount = mono_array_length_internal (params);
- uintptr_t * const lengths = g_newa (uintptr_t, pcount);
- /* Note: the synthetized array .ctors have int32 as argument type */
- for (i = 0; i < pcount; ++i)
- lengths [i] = *(int32_t*) ((char*)mono_array_get_internal (params, gpointer, i) + sizeof (MonoObject));
- if (m_class_get_rank (m->klass) == 1 && sig->param_count == 2 && m_class_get_rank (m_class_get_element_class (m->klass))) {
- /* This is a ctor for jagged arrays. MS creates an array of arrays. */
- arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, error);
- goto_if_nok (error, return_null);
- MonoArrayHandle subarray_handle = MONO_HANDLE_NEW (MonoArray, NULL);
- for (i = 0; i < mono_array_length_internal (arr); ++i) {
- MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m_class_get_element_class (m->klass), &lengths [1], NULL, error);
- goto_if_nok (error, return_null);
- MONO_HANDLE_ASSIGN_RAW (subarray_handle, subarray); // FIXME? Overkill?
- mono_array_setref_fast (arr, i, subarray);
- }
- goto exit;
- }
- if (m_class_get_rank (m->klass) == pcount) {
- /* Only lengths provided. */
- arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, error);
- goto_if_nok (error, return_null);
- goto exit;
- } else {
- g_assert (pcount == (m_class_get_rank (m->klass) * 2));
- /* The arguments are lower-bound-length pairs */
- intptr_t * const lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
- for (i = 0; i < pcount / 2; ++i) {
- lower_bounds [i] = *(int32_t*) ((char*)mono_array_get_internal (params, gpointer, (i * 2)) + sizeof (MonoObject));
- lengths [i] = *(int32_t*) ((char*)mono_array_get_internal (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
- }
- arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, error);
- goto_if_nok (error, return_null);
- goto exit;
- }
- }
- result = mono_runtime_invoke_array_checked (m, obj, params, error);
- goto exit;
- return_null:
- result = NULL;
- arr = NULL;
- exit:
- if (exception) {
- MONO_HANDLE_NEW (MonoException, exception); // FIXME? overkill?
- mono_gc_wbarrier_generic_store_internal (MONO_HANDLE_REF (exception_out), (MonoObject*)exception);
- }
- g_free (target_name);
- g_free (this_name);
- g_free (msg);
- g_assert (!result || !arr); // only one, or neither, should be set
- return result ? MONO_HANDLE_NEW (MonoObject, result) : arr ? MONO_HANDLE_NEW (MonoObject, (MonoObject*)arr) : NULL_HANDLE;
- }
- #ifndef DISABLE_REMOTING
- static void
- internal_execute_field_getter (MonoDomain *domain, MonoObject *this_arg, MonoArray *params, MonoArrayHandleOut outArgs, MonoError *error)
- {
- MonoArray *out_args;
- MonoClass *k = mono_object_class (this_arg);
- MonoString *name;
- char *str;
- // FIXME Refactor/inline internal_execute_field_setter and internal_execute_field_getter.
- /* If this is a proxy, then it must be a CBO */
- if (mono_class_is_transparent_proxy (k)) {
- MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
- this_arg = tp->rp->unwrapped_server;
- MONO_HANDLE_NEW (MonoObject, this_arg);
- g_assert (this_arg);
- k = mono_object_class (this_arg);
- }
-
- name = mono_array_get_internal (params, MonoString *, 1);
- MONO_HANDLE_NEW (MonoString, name);
- str = mono_string_to_utf8_checked_internal (name, error);
- return_if_nok (error);
- do {
- MonoClassField* field = mono_class_get_field_from_name_full (k, str, NULL);
- if (field) {
- g_free (str);
- MonoClass *field_klass = mono_class_from_mono_type_internal (field->type);
- MonoObject *result;
- if (m_class_is_valuetype (field_klass)) {
- result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, error);
- return_if_nok (error);
- } else
- result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
- MONO_HANDLE_NEW (MonoObject, result);
- out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, error);
- return_if_nok (error);
- MONO_HANDLE_NEW (MonoArray, out_args); // FIXME? overkill?
- mono_gc_wbarrier_generic_store_internal (MONO_HANDLE_REF (outArgs), (MonoObject*) out_args);
- mono_array_setref_internal (out_args, 0, result);
- return;
- }
- k = m_class_get_parent (k);
- } while (k);
- g_free (str);
- g_assert_not_reached ();
- }
- static void
- internal_execute_field_setter (MonoDomain *domain, MonoObject *this_arg, MonoArray *params, MonoArrayHandleOut outArgs, MonoError *error)
- {
- MonoArray *out_args;
- MonoClass *k = mono_object_class (this_arg);
- MonoString *name;
- guint32 size;
- gint32 align;
- char *str;
-
- /* If this is a proxy, then it must be a CBO */
- if (mono_class_is_transparent_proxy (k)) {
- MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
- this_arg = tp->rp->unwrapped_server;
- MONO_HANDLE_NEW (MonoObject, this_arg);
- g_assert (this_arg);
- k = mono_object_class (this_arg);
- }
-
- name = mono_array_get_internal (params, MonoString *, 1);
- MONO_HANDLE_NEW (MonoString, name);
- str = mono_string_to_utf8_checked_internal (name, error);
- return_if_nok (error);
-
- do {
- MonoClassField* field = mono_class_get_field_from_name_full (k, str, NULL);
- if (field) {
- g_free (str);
- MonoClass *field_klass = mono_class_from_mono_type_internal (field->type);
- MonoObject *val = (MonoObject *)mono_array_get_internal (params, gpointer, 2);
- MONO_HANDLE_NEW (MonoObject, val);
- if (m_class_is_valuetype (field_klass)) {
- size = mono_type_size (field->type, &align);
- g_assert (size == mono_class_value_size (field_klass, NULL));
- mono_gc_wbarrier_value_copy_internal ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
- } else {
- mono_gc_wbarrier_set_field_internal (this_arg, (char*)this_arg + field->offset, val);
- }
- out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, error);
- return_if_nok (error);
- MONO_HANDLE_NEW (MonoArray, out_args); // FIXME? overkill?
- mono_gc_wbarrier_generic_store_internal (MONO_HANDLE_REF (outArgs), (MonoObject*) out_args);
- return;
- }
-
- k = m_class_get_parent (k);
- } while (k);
- g_free (str);
- g_assert_not_reached ();
- }
- MonoObjectHandle
- ves_icall_InternalExecute (MonoReflectionMethodHandle method_handle, MonoObjectHandle this_arg_handle, MonoArrayHandle params_handle, MonoArrayHandleOut outArgs, MonoError* error)
- {
- MONO_HANDLE_ASSIGN_RAW (outArgs, NULL);
- MonoReflectionMethod* const method = MONO_HANDLE_RAW (method_handle);
- MonoObject* const this_arg = MONO_HANDLE_RAW (this_arg_handle);
- MonoArray* const params = MONO_HANDLE_RAW (params_handle);
- MonoObjectHandle null_handle = NULL_HANDLE_INIT;
- MonoDomain *domain = mono_object_domain (method);
- MonoMethod *m = method->method;
- MonoMethodSignature *sig = mono_method_signature_internal (m);
- MonoArray *out_args;
- MonoObject *result;
- int i, j, outarg_count = 0;
- if (m->klass == mono_defaults.object_class) {
- if (!strcmp (m->name, "FieldGetter")) {
- internal_execute_field_getter (domain, this_arg, params, outArgs, error);
- return null_handle;
- } else if (!strcmp (m->name, "FieldSetter")) {
- internal_execute_field_setter (domain, this_arg, params, outArgs, error);
- return null_handle;
- }
- }
- for (i = 0; i < mono_array_length_internal (params); i++) {
- if (sig->params [i]->byref)
- outarg_count++;
- }
- out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, error);
- return_val_if_nok (error, null_handle);
- MONO_HANDLE_NEW (MonoArray, out_args);
- /* handle constructors only for objects already allocated */
- if (!strcmp (method->method->name, ".ctor"))
- g_assert (this_arg);
- /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
- g_assert (!m_class_is_valuetype (method->method->klass));
- result = mono_runtime_invoke_array_checked (method->method, this_arg, params, error);
- return_val_if_nok (error, null_handle);
- MonoObjectHandle result_handle = MONO_HANDLE_NEW (MonoObject, result);
- MonoObjectHandle arg_handle = MONO_HANDLE_NEW (MonoObject, NULL);
- for (i = 0, j = 0; i < mono_array_length_internal (params); i++) {
- if (sig->params [i]->byref) {
- gpointer arg;
- arg = mono_array_get_internal (params, gpointer, i);
- MONO_HANDLE_ASSIGN_RAW (arg_handle, arg); // FIXME? overkill?
- mono_array_setref_internal (out_args, j, arg);
- j++;
- }
- }
- mono_gc_wbarrier_generic_store_internal (MONO_HANDLE_REF (outArgs), (MonoObject*)out_args);
- return result_handle;
- }
- #endif
- static guint64
- read_enum_value (const char *mem, int type)
- {
- switch (type) {
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_U1:
- return *(guint8*)mem;
- case MONO_TYPE_I1:
- return *(gint8*)mem;
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U2:
- return read16 (mem);
- case MONO_TYPE_I2:
- return (gint16) read16 (mem);
- case MONO_TYPE_U4:
- case MONO_TYPE_R4:
- return read32 (mem);
- case MONO_TYPE_I4:
- return (gint32) read32 (mem);
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- case MONO_TYPE_R8:
- return read64 (mem);
- case MONO_TYPE_U:
- case MONO_TYPE_I:
- #if SIZEOF_REGISTER == 8
- return read64 (mem);
- #else
- return read32 (mem);
- #endif
- default:
- g_assert_not_reached ();
- }
- return 0;
- }
- static void
- write_enum_value (void *mem, int type, guint64 value)
- {
- switch (type) {
- case MONO_TYPE_U1:
- case MONO_TYPE_I1:
- case MONO_TYPE_BOOLEAN: {
- guint8 *p = (guint8*)mem;
- *p = value;
- break;
- }
- case MONO_TYPE_U2:
- case MONO_TYPE_I2:
- case MONO_TYPE_CHAR: {
- guint16 *p = (guint16 *)mem;
- *p = value;
- break;
- }
- case MONO_TYPE_U4:
- case MONO_TYPE_I4:
- case MONO_TYPE_R4: {
- guint32 *p = (guint32 *)mem;
- *p = value;
- break;
- }
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- case MONO_TYPE_R8: {
- guint64 *p = (guint64 *)mem;
- *p = value;
- break;
- }
- case MONO_TYPE_U:
- case MONO_TYPE_I: {
- #if SIZEOF_REGISTER == 8
- guint64 *p = (guint64 *)mem;
- *p = value;
- #else
- guint32 *p = (guint32 *)mem;
- *p = value;
- break;
- #endif
- break;
- }
- default:
- g_assert_not_reached ();
- }
- return;
- }
- MonoObjectHandle
- ves_icall_System_Enum_ToObject (MonoReflectionTypeHandle enumType, guint64 value, MonoError *error)
- {
- MonoDomain *domain;
- MonoClass *enumc;
- MonoObjectHandle resultHandle;
- MonoType *etype;
- domain = MONO_HANDLE_DOMAIN (enumType);
- enumc = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (enumType, type));
- mono_class_init_checked (enumc, error);
- goto_if_nok (error, return_null);
- etype = mono_class_enum_basetype_internal (enumc);
- resultHandle = mono_object_new_handle (domain, enumc, error);
- goto_if_nok (error, return_null);
- write_enum_value (mono_handle_unbox_unsafe (resultHandle), etype->type, value);
- return resultHandle;
- return_null:
- return MONO_HANDLE_NEW (MonoObject, NULL);
- }
- MonoBoolean
- ves_icall_System_Enum_InternalHasFlag (MonoObjectHandle a, MonoObjectHandle b, MonoError *error)
- {
- int size = mono_class_value_size (mono_handle_class (a), NULL);
- guint64 a_val = 0, b_val = 0;
- memcpy (&a_val, mono_handle_unbox_unsafe (a), size);
- memcpy (&b_val, mono_handle_unbox_unsafe (b), size);
- return (a_val & b_val) == b_val;
- }
- #ifndef ENABLE_NETCORE
- MonoObjectHandle
- ves_icall_System_Enum_get_value (MonoObjectHandle ehandle, MonoError *error)
- {
- MonoObjectHandle resultHandle;
- MonoClass *enumc;
- int size;
- goto_if (MONO_HANDLE_IS_NULL (ehandle), return_null);
- g_assert (m_class_is_enumtype (mono_handle_class (ehandle)));
- enumc = mono_class_from_mono_type_internal (mono_class_enum_basetype_internal (mono_handle_class (ehandle)));
- resultHandle = mono_object_new_handle (MONO_HANDLE_DOMAIN (ehandle), enumc, error);
- goto_if_nok (error, return_null);
- size = mono_class_value_size (enumc, NULL);
- memcpy (mono_handle_unbox_unsafe (resultHandle), mono_handle_unbox_unsafe (ehandle), size);
- return resultHandle;
- return_null:
- return MONO_HANDLE_NEW (MonoObject, NULL);
- }
- #endif
- MonoReflectionTypeHandle
- ves_icall_System_Enum_get_underlying_type (MonoReflectionTypeHandle type, MonoError *error)
- {
- MonoType *etype;
- MonoClass *klass;
- klass = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (type, type));
- mono_class_init_checked (klass, error);
- goto_if_nok (error, return_null);
- etype = mono_class_enum_basetype_internal (klass);
- if (!etype) {
- mono_error_set_argument (error, "enumType", "Type provided must be an Enum.");
- goto return_null;
- }
- return mono_type_get_object_handle (MONO_HANDLE_DOMAIN (type), etype, error);
- return_null:
- return MONO_HANDLE_NEW (MonoReflectionType, NULL);
- }
- int
- ves_icall_System_Enum_InternalGetCorElementType (MonoObjectHandle this_handle, MonoError *error)
- {
- MonoClass *klass = MONO_HANDLE_GETVAL (this_handle, vtable)->klass;
- return (int)m_class_get_byval_arg (m_class_get_element_class (klass))->type;
- }
- #ifndef ENABLE_NETCORE
- int
- ves_icall_System_Enum_compare_value_to (MonoObjectHandle enumHandle, MonoObjectHandle otherHandle, MonoError *error)
- {
- if (MONO_HANDLE_IS_NULL (otherHandle))
- return 1;
- if (MONO_HANDLE_GETVAL (enumHandle, vtable)->klass != MONO_HANDLE_GETVAL (otherHandle, vtable)->klass)
- return 2;
- gpointer tdata = mono_handle_unbox_unsafe (enumHandle);
- gpointer odata = mono_handle_unbox_unsafe (otherHandle);
- MonoType *basetype = mono_class_enum_basetype_internal (MONO_HANDLE_GETVAL (enumHandle, vtable)->klass);
- g_assert (basetype);
- #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
- ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
- ENUM_TYPE other = *((ENUM_TYPE*)odata); \
- if (me == other) \
- return 0; \
- return me > other ? 1 : -1; \
- } while (0)
- switch (basetype->type) {
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_U1:
- COMPARE_ENUM_VALUES (guint8);
- case MONO_TYPE_I1:
- COMPARE_ENUM_VALUES (gint8);
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U2:
- COMPARE_ENUM_VALUES (guint16);
- case MONO_TYPE_I2:
- COMPARE_ENUM_VALUES (gint16);
- case MONO_TYPE_U4:
- COMPARE_ENUM_VALUES (guint32);
- case MONO_TYPE_I4:
- COMPARE_ENUM_VALUES (gint32);
- case MONO_TYPE_R4:
- COMPARE_ENUM_VALUES (gfloat);
- case MONO_TYPE_U8:
- COMPARE_ENUM_VALUES (guint64);
- case MONO_TYPE_I8:
- COMPARE_ENUM_VALUES (gint64);
- case MONO_TYPE_R8:
- COMPARE_ENUM_VALUES (gdouble);
- case MONO_TYPE_U:
- #if SIZEOF_REGISTER == 8
- COMPARE_ENUM_VALUES (guint64);
- #else
- COMPARE_ENUM_VALUES (guint32);
- #endif
- case MONO_TYPE_I:
- #if SIZEOF_REGISTER == 8
- COMPARE_ENUM_VALUES (gint64);
- #else
- COMPARE_ENUM_VALUES (gint32);
- #endif
- default:
- break;
- }
- #undef COMPARE_ENUM_VALUES
- /* indicates that the enum was of an unsupported underlying type */
- return 3;
- }
- #endif
- #ifndef ENABLE_NETCORE
- int
- ves_icall_System_Enum_get_hashcode (MonoObjectHandle enumHandle, MonoError *error)
- {
- gpointer data = mono_handle_unbox_unsafe (enumHandle);
- MonoType *basetype = mono_class_enum_basetype_internal (MONO_HANDLE_GETVAL (enumHandle, vtable)->klass);
- g_assert (basetype);
- switch (basetype->type) {
- case MONO_TYPE_I1: {
- gint8 value = *((gint8*)data);
- return ((int)value ^ (int)value << 8);
- }
- case MONO_TYPE_U1:
- return *((guint8*)data);
- case MONO_TYPE_CHAR:
- case MONO_TYPE_U2:
- return *((guint16*)data);
-
- case MONO_TYPE_I2: {
- gint16 value = *((gint16*)data);
- return ((int)(guint16)value | (((int)value) << 16));
- }
- case MONO_TYPE_U4:
- case MONO_TYPE_R4:
- return *((guint32*)data);
- case MONO_TYPE_I4:
- return *((gint32*)data);
- case MONO_TYPE_U8:
- case MONO_TYPE_I8:
- case MONO_TYPE_R8: {
- gint64 value = *((gint64*)data);
- return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
- }
- case MONO_TYPE_I:
- case MONO_TYPE_U: {
- #if SIZEOF_REGISTER == 8
- gint64 value = *((gint64*)data);
- return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
- #else
- return *((guint32*)data);
- #endif
- }
- default:
- g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
- }
- return 0;
- }
- #endif
- static void
- get_enum_field (MonoDomain *domain, MonoArrayHandle names, MonoArrayHandle values, int base_type, MonoClassField *field, guint* j, guint64 *previous_value, gboolean *sorted, MonoError *error)
- {
- error_init (error);
- HANDLE_FUNCTION_ENTER();
- guint64 field_value;
- const char *p;
- MonoTypeEnum def_type;
- if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
- goto leave;
- if (strcmp ("value__", mono_field_get_name (field)) == 0)
- goto leave;
- if (mono_field_is_deleted (field))
- goto leave;
- MonoStringHandle name;
- name = mono_string_new_handle (domain, mono_field_get_name (field), error);
- goto_if_nok (error, leave);
- MONO_HANDLE_ARRAY_SETREF (names, *j, name);
- p = mono_class_get_field_default_value (field, &def_type);
- /* len = */ mono_metadata_decode_blob_size (p, &p);
- field_value = read_enum_value (p, base_type);
- MONO_HANDLE_ARRAY_SETVAL (values, guint64, *j, field_value);
- if (*previous_value > field_value)
- *sorted = FALSE;
- *previous_value = field_value;
- (*j)++;
- leave:
- HANDLE_FUNCTION_RETURN();
- }
- MonoBoolean
- ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionTypeHandle type, MonoArrayHandleOut values, MonoArrayHandleOut names, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (type);
- MonoClass *enumc = mono_class_from_mono_type_internal (MONO_HANDLE_RAW(type)->type);
- guint j = 0, nvalues;
- gpointer iter;
- MonoClassField *field;
- int base_type;
- guint64 previous_value = 0;
- gboolean sorted = TRUE;
- error_init (error);
- mono_class_init_checked (enumc, error);
- return_val_if_nok (error, FALSE);
- if (!m_class_is_enumtype (enumc)) {
- #if ENABLE_NETCORE
- mono_error_set_argument (error, NULL, "Type provided must be an Enum.");
- #else
- mono_error_set_argument (error, "enumType", "Type provided must be an Enum.");
- #endif
- return TRUE;
- }
- base_type = mono_class_enum_basetype_internal (enumc)->type;
- nvalues = mono_class_num_fields (enumc) > 0 ? mono_class_num_fields (enumc) - 1 : 0;
- MONO_HANDLE_ASSIGN(names, mono_array_new_handle (domain, mono_defaults.string_class, nvalues, error));
- return_val_if_nok (error, FALSE);
- MONO_HANDLE_ASSIGN(values, mono_array_new_handle (domain, mono_defaults.uint64_class, nvalues, error));
- return_val_if_nok (error, FALSE);
- iter = NULL;
- while ((field = mono_class_get_fields_internal (enumc, &iter))) {
- get_enum_field(domain, names, values, base_type, field, &j, &previous_value, &sorted, error);
- if (!is_ok (error))
- break;
- }
- return_val_if_nok (error, FALSE);
- return sorted || base_type == MONO_TYPE_R4 || base_type == MONO_TYPE_R8;
- }
- enum {
- BFLAGS_IgnoreCase = 1,
- BFLAGS_DeclaredOnly = 2,
- BFLAGS_Instance = 4,
- BFLAGS_Static = 8,
- BFLAGS_Public = 0x10,
- BFLAGS_NonPublic = 0x20,
- BFLAGS_FlattenHierarchy = 0x40,
- BFLAGS_InvokeMethod = 0x100,
- BFLAGS_CreateInstance = 0x200,
- BFLAGS_GetField = 0x400,
- BFLAGS_SetField = 0x800,
- BFLAGS_GetProperty = 0x1000,
- BFLAGS_SetProperty = 0x2000,
- BFLAGS_ExactBinding = 0x10000,
- BFLAGS_SuppressChangeType = 0x20000,
- BFLAGS_OptionalParamBinding = 0x40000
- };
- enum {
- MLISTTYPE_All = 0,
- MLISTTYPE_CaseSensitive = 1,
- MLISTTYPE_CaseInsensitive = 2,
- MLISTTYPE_HandleToInfo = 3
- };
- GPtrArray*
- ves_icall_RuntimeType_GetFields_native (MonoReflectionTypeHandle ref_type, char *utf8_name, guint32 bflags, guint32 mlisttype, MonoError *error)
- {
- error_init (error);
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- if (type->byref) {
- return g_ptr_array_new ();
- }
- int (*compare_func) (const char *s1, const char *s2) = NULL;
- compare_func = ((bflags & BFLAGS_IgnoreCase) || (mlisttype == MLISTTYPE_CaseInsensitive)) ? mono_utf8_strcasecmp : strcmp;
- MonoClass *startklass, *klass;
- klass = startklass = mono_class_from_mono_type_internal (type);
- GPtrArray *ptr_array = g_ptr_array_sized_new (16);
-
- handle_parent:
- if (mono_class_has_failure (klass)) {
- mono_error_set_for_class_failure (error, klass);
- goto fail;
- }
- MonoClassField *field;
- gpointer iter;
- iter = NULL;
- while ((field = mono_class_get_fields_lazy (klass, &iter))) {
- guint32 flags = mono_field_get_flags (field);
- int match = 0;
- if (mono_field_is_deleted_with_flags (field, flags))
- continue;
- if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
- if (bflags & BFLAGS_Public)
- match++;
- } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
- if (bflags & BFLAGS_NonPublic) {
- match++;
- }
- }
- if (!match)
- continue;
- match = 0;
- if (flags & FIELD_ATTRIBUTE_STATIC) {
- if (bflags & BFLAGS_Static)
- if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
- match++;
- } else {
- if (bflags & BFLAGS_Instance)
- match++;
- }
- if (!match)
- continue;
- if (((mlisttype != MLISTTYPE_All) && (utf8_name != NULL)) && compare_func (mono_field_get_name (field), utf8_name))
- continue;
- g_ptr_array_add (ptr_array, field);
- }
- if (!(bflags & BFLAGS_DeclaredOnly) && (klass = m_class_get_parent (klass)))
- goto handle_parent;
- return ptr_array;
- fail:
- g_ptr_array_free (ptr_array, TRUE);
- return NULL;
- }
- static gboolean
- method_nonpublic (MonoMethod* method, gboolean start_klass)
- {
- switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
- case METHOD_ATTRIBUTE_ASSEM:
- return TRUE;
- case METHOD_ATTRIBUTE_PRIVATE:
- return start_klass;
- case METHOD_ATTRIBUTE_PUBLIC:
- return FALSE;
- default:
- return TRUE;
- }
- }
- GPtrArray*
- mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, guint32 mlisttype, gboolean allow_ctors, MonoError *error)
- {
- GPtrArray *array;
- MonoClass *startklass;
- MonoMethod *method;
- gpointer iter;
- int match, nslots;
- /*FIXME, use MonoBitSet*/
- guint32 method_slots_default [8];
- guint32 *method_slots = NULL;
- int (*compare_func) (const char *s1, const char *s2) = NULL;
- array = g_ptr_array_new ();
- startklass = klass;
- error_init (error);
-
- compare_func = ((bflags & BFLAGS_IgnoreCase) || (mlisttype == MLISTTYPE_CaseInsensitive)) ? mono_utf8_strcasecmp : strcmp;
- /* An optimization for calls made from Delegate:CreateDelegate () */
- if (m_class_is_delegate (klass) && klass != mono_defaults.delegate_class && klass != mono_defaults.multicastdelegate_class && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
- method = mono_get_delegate_invoke_internal (klass);
- g_assert (method);
- g_ptr_array_add (array, method);
- return array;
- }
- mono_class_setup_methods (klass);
- mono_class_setup_vtable (klass);
- if (mono_class_has_failure (klass))
- goto loader_error;
- if (is_generic_parameter (m_class_get_byval_arg (klass)))
- nslots = mono_class_get_vtable_size (m_class_get_parent (klass));
- else
- nslots = MONO_CLASS_IS_INTERFACE_INTERNAL (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
- if (nslots >= sizeof (method_slots_default) * 8) {
- method_slots = g_new0 (guint32, nslots / 32 + 1);
- } else {
- method_slots = method_slots_default;
- memset (method_slots, 0, sizeof (method_slots_default));
- }
- handle_parent:
- mono_class_setup_methods (klass);
- mono_class_setup_vtable (klass);
- if (mono_class_has_failure (klass))
- goto loader_error;
- iter = NULL;
- while ((method = mono_class_get_methods (klass, &iter))) {
- match = 0;
- if (method->slot != -1) {
- g_assert (method->slot < nslots);
- if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
- continue;
- if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
- method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
- }
- if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
- continue;
- if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
- if (bflags & BFLAGS_Public)
- match++;
- } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
- match++;
- }
- if (!match)
- continue;
- match = 0;
- if (method->flags & METHOD_ATTRIBUTE_STATIC) {
- if (bflags & BFLAGS_Static)
- if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
- match++;
- } else {
- if (bflags & BFLAGS_Instance)
- match++;
- }
- if (!match)
- continue;
- if ((mlisttype != MLISTTYPE_All) && (name != NULL)) {
- if (compare_func (name, method->name))
- continue;
- }
-
- match = 0;
- g_ptr_array_add (array, method);
- }
- if (!(bflags & BFLAGS_DeclaredOnly) && (klass = m_class_get_parent (klass)))
- goto handle_parent;
- if (method_slots != method_slots_default)
- g_free (method_slots);
- return array;
- loader_error:
- if (method_slots != method_slots_default)
- g_free (method_slots);
- g_ptr_array_free (array, TRUE);
- g_assert (mono_class_has_failure (klass));
- mono_error_set_for_class_failure (error, klass);
- return NULL;
- }
- GPtrArray*
- ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionTypeHandle ref_type, const char *mname, guint32 bflags, guint32 mlisttype, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- if (type->byref) {
- return g_ptr_array_new ();
- }
- return mono_class_get_methods_by_name (klass, mname, bflags, mlisttype, FALSE, error);
- }
- GPtrArray*
- ves_icall_RuntimeType_GetConstructors_native (MonoReflectionTypeHandle ref_type, guint32 bflags, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- if (type->byref) {
- return g_ptr_array_new ();
- }
- MonoClass *startklass, *klass;
- klass = startklass = mono_class_from_mono_type_internal (type);
- mono_class_setup_methods (klass);
- if (mono_class_has_failure (klass)) {
- mono_error_set_for_class_failure (error, klass);
- return NULL;
- }
-
- GPtrArray *res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
- MonoMethod *method;
- gpointer iter = NULL;
- while ((method = mono_class_get_methods (klass, &iter))) {
- int match = 0;
- if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
- continue;
- if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
- if (bflags & BFLAGS_Public)
- match++;
- } else {
- if (bflags & BFLAGS_NonPublic)
- match++;
- }
- if (!match)
- continue;
- match = 0;
- if (method->flags & METHOD_ATTRIBUTE_STATIC) {
- if (bflags & BFLAGS_Static)
- if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
- match++;
- } else {
- if (bflags & BFLAGS_Instance)
- match++;
- }
- if (!match)
- continue;
- g_ptr_array_add (res_array, method);
- }
- return res_array;
- }
- static guint
- property_hash (gconstpointer data)
- {
- MonoProperty *prop = (MonoProperty*)data;
- return g_str_hash (prop->name);
- }
- static gboolean
- property_accessor_override (MonoMethod *method1, MonoMethod *method2)
- {
- if (method1->slot != -1 && method1->slot == method2->slot)
- return TRUE;
- if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
- if (method1->is_inflated)
- method1 = ((MonoMethodInflated*) method1)->declaring;
- if (method2->is_inflated)
- method2 = ((MonoMethodInflated*) method2)->declaring;
- }
- return mono_metadata_signature_equal (mono_method_signature_internal (method1), mono_method_signature_internal (method2));
- }
- static gboolean
- property_equal (MonoProperty *prop1, MonoProperty *prop2)
- {
- // Properties are hide-by-name-and-signature
- if (!g_str_equal (prop1->name, prop2->name))
- return FALSE;
- /* If we see a property in a generic method, we want to
- compare the generic signatures, not the inflated signatures
- because we might conflate two properties that were
- distinct:
- class Foo<T,U> {
- public T this[T t] { getter { return t; } } // method 1
- public U this[U u] { getter { return u; } } // method 2
- }
- If we see int Foo<int,int>::Item[int] we need to know if
- the indexer came from method 1 or from method 2, and we
- shouldn't conflate them. (Bugzilla 36283)
- */
- if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
- return FALSE;
- if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
- return FALSE;
- return TRUE;
- }
- static gboolean
- property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
- {
- if (!accessor)
- return FALSE;
- return method_nonpublic (accessor, start_klass);
- }
- GPtrArray*
- ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionTypeHandle ref_type, gchar *propname, guint32 bflags, guint32 mlisttype, MonoError *error)
- {
- #if ENABLE_NETCORE
- // Fetch non-public properties as well because they can hide public properties with the same name in base classes
- bflags |= BFLAGS_NonPublic;
- #endif
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- if (type->byref) {
- return g_ptr_array_new ();
- }
-
- MonoClass *startklass, *klass;
- klass = startklass = mono_class_from_mono_type_internal (type);
- int (*compare_func) (const char *s1, const char *s2) = (mlisttype == MLISTTYPE_CaseInsensitive) ? mono_utf8_strcasecmp : strcmp;
- GPtrArray *res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
- GHashTable *properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
- handle_parent:
- mono_class_setup_methods (klass);
- mono_class_setup_vtable (klass);
- if (mono_class_has_failure (klass)) {
- mono_error_set_for_class_failure (error, klass);
- goto loader_error;
- }
- MonoProperty *prop;
- gpointer iter;
- iter = NULL;
- while ((prop = mono_class_get_properties (klass, &iter))) {
- int match = 0;
- MonoMethod *method = prop->get;
- if (!method)
- method = prop->set;
- guint32 flags = 0;
- if (method)
- flags = method->flags;
- if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
- (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
- if (bflags & BFLAGS_Public)
- match++;
- } else if (bflags & BFLAGS_NonPublic) {
- if (property_accessor_nonpublic(prop->get, startklass == klass) ||
- property_accessor_nonpublic(prop->set, startklass == klass)) {
- match++;
- }
- }
- if (!match)
- continue;
- match = 0;
- if (flags & METHOD_ATTRIBUTE_STATIC) {
- if (bflags & BFLAGS_Static)
- if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
- match++;
- } else {
- if (bflags & BFLAGS_Instance)
- match++;
- }
- if (!match)
- continue;
- match = 0;
- if ((mlisttype != MLISTTYPE_All) && (propname != NULL) && compare_func (propname, prop->name))
- continue;
-
- if (g_hash_table_lookup (properties, prop))
- continue;
- g_ptr_array_add (res_array, prop);
-
- g_hash_table_insert (properties, prop, prop);
- }
- if (!(bflags & BFLAGS_DeclaredOnly) && (klass = m_class_get_parent (klass))) {
- #if ENABLE_NETCORE
- // BFLAGS_NonPublic should be excluded for base classes
- bflags &= ~BFLAGS_NonPublic;
- #endif
- goto handle_parent;
- }
- g_hash_table_destroy (properties);
- return res_array;
- loader_error:
- if (properties)
- g_hash_table_destroy (properties);
- g_ptr_array_free (res_array, TRUE);
- return NULL;
- }
- static guint
- event_hash (gconstpointer data)
- {
- MonoEvent *event = (MonoEvent*)data;
- return g_str_hash (event->name);
- }
- static gboolean
- event_equal (MonoEvent *event1, MonoEvent *event2)
- {
- // Events are hide-by-name
- return g_str_equal (event1->name, event2->name);
- }
- GPtrArray*
- ves_icall_RuntimeType_GetEvents_native (MonoReflectionTypeHandle ref_type, char *utf8_name, guint32 mlisttype, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- if (type->byref) {
- return g_ptr_array_new ();
- }
- int (*compare_func) (const char *s1, const char *s2) = (mlisttype == MLISTTYPE_CaseInsensitive) ? mono_utf8_strcasecmp : strcmp;
- GPtrArray *res_array = g_ptr_array_sized_new (4);
- MonoClass *startklass, *klass;
- klass = startklass = mono_class_from_mono_type_internal (type);
- GHashTable *events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
- handle_parent:
- mono_class_setup_methods (klass);
- mono_class_setup_vtable (klass);
- if (mono_class_has_failure (klass)) {
- mono_error_set_for_class_failure (error, klass);
- goto failure;
- }
- MonoEvent *event;
- gpointer iter;
- iter = NULL;
- while ((event = mono_class_get_events (klass, &iter))) {
- // Remove inherited privates and inherited
- // without add/remove/raise methods
- if (klass != startklass)
- {
- MonoMethod *method = event->add;
- if (!method)
- method = event->remove;
- if (!method)
- method = event->raise;
- if (!method)
- continue;
- if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
- continue;
- }
- if ((mlisttype != MLISTTYPE_All) && (utf8_name != NULL) && compare_func (event->name, utf8_name))
- continue;
- if (g_hash_table_lookup (events, event))
- continue;
- g_ptr_array_add (res_array, event);
- g_hash_table_insert (events, event, event);
- }
- if ((klass = m_class_get_parent (klass)))
- goto handle_parent;
- g_hash_table_destroy (events);
- return res_array;
- failure:
- if (events != NULL)
- g_hash_table_destroy (events);
- g_ptr_array_free (res_array, TRUE);
- return NULL;
- }
- GPtrArray *
- ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionTypeHandle ref_type, char *str, guint32 bflags, guint32 mlisttype, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- if (type->byref) {
- return g_ptr_array_new ();
- }
- int (*compare_func) (const char *s1, const char *s2) = ((bflags & BFLAGS_IgnoreCase) || (mlisttype == MLISTTYPE_CaseInsensitive)) ? mono_utf8_strcasecmp : strcmp;
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- /*
- * If a nested type is generic, return its generic type definition.
- * Note that this means that the return value is essentially the set
- * of nested types of the generic type definition of @klass.
- *
- * A note in MSDN claims that a generic type definition can have
- * nested types that aren't generic. In any case, the container of that
- * nested type would be the generic type definition.
- */
- if (mono_class_is_ginst (klass))
- klass = mono_class_get_generic_class (klass)->container_class;
- GPtrArray *res_array = g_ptr_array_new ();
-
- MonoClass *nested;
- gpointer iter = NULL;
- while ((nested = mono_class_get_nested_types (klass, &iter))) {
- int match = 0;
- if ((mono_class_get_flags (nested) & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
- if (bflags & BFLAGS_Public)
- match++;
- } else {
- if (bflags & BFLAGS_NonPublic)
- match++;
- }
- if (!match)
- continue;
- if ((mlisttype != MLISTTYPE_All) && (str != NULL) && compare_func (m_class_get_name (nested), str))
- continue;
- g_ptr_array_add (res_array, m_class_get_byval_arg (nested));
- }
- return res_array;
- }
- static MonoType*
- get_type_from_module_builder_module (MonoAssemblyLoadContext *alc, MonoArrayHandle modules, int i, MonoTypeNameParse *info, MonoBoolean ignoreCase, gboolean *type_resolve, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- MonoType *type = NULL;
- MonoReflectionModuleBuilderHandle mb = MONO_HANDLE_NEW (MonoReflectionModuleBuilder, NULL);
- MONO_HANDLE_ARRAY_GETREF (mb, modules, i);
- MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (mb, dynamic_image);
- type = mono_reflection_get_type_checked (alc, &dynamic_image->image, &dynamic_image->image, info, ignoreCase, FALSE, type_resolve, error);
- HANDLE_FUNCTION_RETURN_VAL (type);
- }
- static MonoType*
- get_type_from_module_builder_loaded_modules (MonoAssemblyLoadContext *alc, MonoArrayHandle loaded_modules, int i, MonoTypeNameParse *info, MonoBoolean ignoreCase, gboolean *type_resolve, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- MonoType *type = NULL;
- MonoReflectionModuleHandle mod = MONO_HANDLE_NEW (MonoReflectionModule, NULL);
- MONO_HANDLE_ARRAY_GETREF (mod, loaded_modules, i);
- MonoImage *image = MONO_HANDLE_GETVAL (mod, image);
- type = mono_reflection_get_type_checked (alc, image, image, info, ignoreCase, FALSE, type_resolve, error);
- HANDLE_FUNCTION_RETURN_VAL (type);
- }
- MonoReflectionTypeHandle
- ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssemblyHandle assembly_h, MonoReflectionModuleHandle module, MonoStringHandle name, MonoBoolean throwOnError, MonoBoolean ignoreCase, MonoError *error)
- {
- ERROR_DECL (parse_error);
- MonoTypeNameParse info;
- gboolean type_resolve;
- MonoAssemblyLoadContext *alc = mono_domain_ambient_alc (mono_domain_get ());
- /* On MS.NET, this does not fire a TypeResolve event */
- type_resolve = TRUE;
- char *str = mono_string_handle_to_utf8 (name, error);
- goto_if_nok (error, fail);
- /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
- if (!mono_reflection_parse_type_checked (str, &info, parse_error)) {
- g_free (str);
- mono_reflection_free_type_info (&info);
- mono_error_cleanup (parse_error);
- if (throwOnError) {
- #if ENABLE_NETCORE
- mono_error_set_argument (error, "typeName@0", "failed to parse the type");
- #else
- mono_error_set_argument (error, "typeName", "failed to parse the type");
- #endif
- goto fail;
- }
- /*g_print ("failed parse\n");*/
- return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
- }
- if (info.assembly.name) {
- g_free (str);
- mono_reflection_free_type_info (&info);
- if (throwOnError) {
- mono_error_set_argument (error, NULL, "Type names passed to Assembly.GetType() must not specify an assembly.");
- goto fail;
- }
- return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
- }
- MonoType *type;
- type = NULL;
- if (!MONO_HANDLE_IS_NULL (module)) {
- MonoImage *image = MONO_HANDLE_GETVAL (module, image);
- if (image) {
- type = mono_reflection_get_type_checked (alc, image, image, &info, ignoreCase, FALSE, &type_resolve, error);
- if (!is_ok (error)) {
- g_free (str);
- mono_reflection_free_type_info (&info);
- goto fail;
- }
- }
- }
- else {
- MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
- if (assembly_is_dynamic (assembly)) {
- /* Enumerate all modules */
- MonoReflectionAssemblyBuilderHandle abuilder = MONO_HANDLE_NEW (MonoReflectionAssemblyBuilder, NULL);
- MONO_HANDLE_ASSIGN (abuilder, assembly_h);
- int i;
- MonoArrayHandle modules = MONO_HANDLE_NEW (MonoArray, NULL);
- MONO_HANDLE_GET (modules, abuilder, modules);
- if (!MONO_HANDLE_IS_NULL (modules)) {
- int n = mono_array_handle_length (modules);
- for (i = 0; i < n; ++i) {
- type = get_type_from_module_builder_module (alc, modules, i, &info, ignoreCase, &type_resolve, error);
- if (!is_ok (error)) {
- g_free (str);
- mono_reflection_free_type_info (&info);
- goto fail;
- }
- if (type)
- break;
- }
- }
- MonoArrayHandle loaded_modules = MONO_HANDLE_NEW (MonoArray, NULL);
- MONO_HANDLE_GET (loaded_modules, abuilder, loaded_modules);
- if (!type && !MONO_HANDLE_IS_NULL (loaded_modules)) {
- int n = mono_array_handle_length (loaded_modules);
- for (i = 0; i < n; ++i) {
- type = get_type_from_module_builder_loaded_modules (alc, loaded_modules, i, &info, ignoreCase, &type_resolve, error);
- if (!is_ok (error)) {
- g_free (str);
- mono_reflection_free_type_info (&info);
- goto fail;
- }
- if (type)
- break;
- }
- }
- }
- else {
- type = mono_reflection_get_type_checked (alc, assembly->image, assembly->image, &info, ignoreCase, FALSE, &type_resolve, error);
- if (!is_ok (error)) {
- g_free (str);
- mono_reflection_free_type_info (&info);
- goto fail;
- }
- }
- }
- g_free (str);
- mono_reflection_free_type_info (&info);
- if (!type) {
- if (throwOnError) {
- ERROR_DECL (inner_error);
- char *type_name = mono_string_handle_to_utf8 (name, inner_error);
- mono_error_assert_ok (inner_error);
- MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
- char *assmname = mono_stringify_assembly_name (&assembly->aname);
- mono_error_set_type_load_name (error, type_name, assmname, "%s", "");
- goto fail;
- }
- return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
- }
- if (type->type == MONO_TYPE_CLASS) {
- MonoClass *klass = mono_type_get_class_internal (type);
- /* need to report exceptions ? */
- if (throwOnError && mono_class_has_failure (klass)) {
- /* report SecurityException (or others) that occured when loading the assembly */
- mono_error_set_for_class_failure (error, klass);
- goto fail;
- }
- }
- /* g_print ("got it\n"); */
- return mono_type_get_object_handle (MONO_HANDLE_DOMAIN (assembly_h), type, error);
- fail:
- g_assert (!is_ok (error));
- return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
- }
- static gboolean
- replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
- {
- gchar *content;
- gchar *shadow_ini_file;
- gsize len;
- /* Check for shadow-copied assembly */
- if (mono_is_shadow_copy_enabled (domain, dirname)) {
- shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", (const char*)NULL);
- content = NULL;
- if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
- !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
- g_free (content);
- content = NULL;
- }
- g_free (shadow_ini_file);
- if (content != NULL) {
- g_free (*filename);
- *filename = content;
- return TRUE;
- }
- }
- return FALSE;
- }
- MonoStringHandle
- ves_icall_System_Reflection_RuntimeAssembly_get_code_base (MonoReflectionAssemblyHandle assembly, MonoBoolean escaped, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly);
- MonoAssembly *mass = MONO_HANDLE_GETVAL (assembly, assembly);
- gchar *absolute;
- gchar *dirname;
-
- if (g_path_is_absolute (mass->image->name)) {
- absolute = g_strdup (mass->image->name);
- dirname = g_path_get_dirname (absolute);
- } else {
- absolute = g_build_filename (mass->basedir, mass->image->name, (const char*)NULL);
- dirname = g_strdup (mass->basedir);
- }
- replace_shadow_path (domain, dirname, &absolute);
- g_free (dirname);
- mono_icall_make_platform_path (absolute);
- gchar *uri;
- if (escaped) {
- uri = g_filename_to_uri (absolute, NULL, NULL);
- } else {
- const gchar *prepend = mono_icall_get_file_path_prefix (absolute);
- uri = g_strconcat (prepend, absolute, (const char*)NULL);
- }
- g_free (absolute);
- MonoStringHandle res;
- if (uri) {
- res = mono_string_new_handle (domain, uri, error);
- g_free (uri);
- } else {
- res = MONO_HANDLE_NEW (MonoString, NULL);
- }
- return res;
- }
- #ifndef ENABLE_NETCORE
- MonoBoolean
- ves_icall_System_Reflection_RuntimeAssembly_get_global_assembly_cache (MonoReflectionAssemblyHandle assembly, MonoError *error)
- {
- MonoAssembly *mass = MONO_HANDLE_GETVAL (assembly,assembly);
- return mass->in_gac;
- }
- MonoReflectionAssemblyHandle
- ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoStringHandle mname, MonoObjectHandle evidence, MonoError *error)
- {
- gchar *name;
- MonoImageOpenStatus status;
- MonoReflectionAssemblyHandle result = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
-
- name = mono_string_handle_to_utf8 (mname, error);
- goto_if_nok (error, leave);
- MonoAssembly *res;
- res = mono_assembly_load_with_partial_name_internal (name, mono_domain_default_alc (mono_domain_get ()), &status);
- g_free (name);
- if (res == NULL)
- goto leave;
- result = mono_assembly_get_object_handle (mono_domain_get (), res, error);
- leave:
- return result;
- }
- #endif
- MonoStringHandle
- ves_icall_System_Reflection_RuntimeAssembly_get_location (MonoReflectionAssemblyHandle refassembly, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
- MonoAssembly *assembly = MONO_HANDLE_GETVAL (refassembly, assembly);
- const char *image_name = m_image_get_filename (assembly->image);
- return mono_string_new_handle (domain, image_name != NULL ? image_name : "", error);
- }
- #ifndef ENABLE_NETCORE
- MonoBoolean
- ves_icall_System_Reflection_RuntimeAssembly_get_ReflectionOnly (MonoReflectionAssemblyHandle assembly_h, MonoError *error)
- {
- MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
- return mono_asmctx_get_kind (&assembly->context) == MONO_ASMCTX_REFONLY;
- }
- #endif
- MonoStringHandle
- ves_icall_System_Reflection_RuntimeAssembly_InternalImageRuntimeVersion (MonoReflectionAssemblyHandle refassembly, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
- MonoAssembly *assembly = MONO_HANDLE_GETVAL (refassembly, assembly);
- return mono_string_new_handle (domain, assembly->image->version, error);
- }
- MonoReflectionMethodHandle
- ves_icall_System_Reflection_RuntimeAssembly_get_EntryPoint (MonoReflectionAssemblyHandle assembly_h, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly_h);
- MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
- MonoMethod *method;
- MonoReflectionMethodHandle res = MONO_HANDLE_NEW (MonoReflectionMethod, NULL);
- guint32 token = mono_image_get_entry_point (assembly->image);
- if (!token)
- goto leave;
- method = mono_get_method_checked (assembly->image, token, NULL, NULL, error);
- goto_if_nok (error, leave);
- MONO_HANDLE_ASSIGN (res, mono_method_get_object_handle (domain, method, NULL, error));
- leave:
- return res;
- }
- MonoReflectionModuleHandle
- ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssemblyHandle assembly, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly);
- MonoAssembly *a = MONO_HANDLE_GETVAL (assembly, assembly);
- return mono_module_get_object_handle (domain, a->image, error);
- }
- static gboolean
- add_manifest_resource_name_to_array (MonoDomain *domain, MonoImage *image, MonoTableInfo *table, int i, MonoArrayHandle dest, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- const char *val = mono_metadata_string_heap (image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
- MonoStringHandle str = mono_string_new_handle (domain, val, error);
- goto_if_nok (error, leave);
- MONO_HANDLE_ARRAY_SETREF (dest, i, str);
- leave:
- HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
- }
- MonoArrayHandle
- ves_icall_System_Reflection_RuntimeAssembly_GetManifestResourceNames (MonoReflectionAssemblyHandle assembly_h, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly_h);
- MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
- MonoTableInfo *table = &assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
- MonoArrayHandle result = mono_array_new_handle (domain, mono_defaults.string_class, table->rows, error);
- goto_if_nok (error, fail);
- int i;
- for (i = 0; i < table->rows; ++i) {
- if (!add_manifest_resource_name_to_array (domain, assembly->image, table, i, result, error))
- goto fail;
- }
- return result;
- fail:
- return NULL_HANDLE_ARRAY;
- }
- #ifndef ENABLE_NETCORE
- MonoBoolean
- ves_icall_System_Reflection_RuntimeAssembly_GetAotIdInternal (MonoArrayHandle guid_h, MonoError *error)
- {
- g_assert (mono_array_handle_length (guid_h) == 16);
- guint8 *aotid = mono_runtime_get_aotid_arr ();
- if (!aotid) {
- return FALSE;
- } else {
- MONO_ENTER_NO_SAFEPOINTS;
- guint8 *data = (guint8*) mono_array_addr_with_size_internal (MONO_HANDLE_RAW (guid_h), 1, 0);
- memcpy (data, aotid, 16);
- MONO_EXIT_NO_SAFEPOINTS;
- return TRUE;
- }
- }
- #endif
- static MonoAssemblyName*
- create_referenced_assembly_name (MonoDomain *domain, MonoImage *image, int i, MonoError *error)
- {
- MonoAssemblyName *aname = g_new0 (MonoAssemblyName, 1);
- mono_assembly_get_assemblyref_checked (image, i, aname, error);
- return_val_if_nok (error, NULL);
- aname->hash_alg = ASSEMBLY_HASH_SHA1 /* SHA1 (default) */;
- /* name and culture are pointers into the image tables, but we need
- * real malloc'd strings (so that we can g_free() them later from
- * Mono.RuntimeMarshal.FreeAssemblyName) */
- aname->name = g_strdup (aname->name);
- aname->culture = g_strdup (aname->culture);
- /* Don't need the hash value in managed */
- aname->hash_value = NULL;
- aname->hash_len = 0;
- g_assert (aname->public_key == NULL);
-
- /* note: this function doesn't return the codebase on purpose (i.e. it can
- be used under partial trust as path information isn't present). */
- return aname;
- }
- GPtrArray*
- ves_icall_System_Reflection_Assembly_InternalGetReferencedAssemblies (MonoReflectionAssemblyHandle assembly, MonoError *error)
- {
- error_init (error);
- MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly);
- MonoAssembly *ass = MONO_HANDLE_GETVAL(assembly, assembly);
- MonoImage *image = ass->image;
- int count;
- if (image_is_dynamic (ass->image)) {
- MonoDynamicTable *t = &(((MonoDynamicImage*) image)->tables [MONO_TABLE_ASSEMBLYREF]);
- count = t->rows;
- }
- else {
- MonoTableInfo *t = &image->tables [MONO_TABLE_ASSEMBLYREF];
- count = t->rows;
- }
- GPtrArray *result = g_ptr_array_sized_new (count);
- for (int i = 0; i < count; i++) {
- MonoAssemblyName *aname = create_referenced_assembly_name (domain, image, i, error);
- if (!is_ok (error))
- break;
- g_ptr_array_add (result, aname);
- }
- return result;
- }
- /* move this in some file in mono/util/ */
- static char *
- g_concat_dir_and_file (const char *dir, const char *file)
- {
- g_return_val_if_fail (dir != NULL, NULL);
- g_return_val_if_fail (file != NULL, NULL);
- /*
- * If the directory name doesn't have a / on the end, we need
- * to add one so we get a proper path to the file
- */
- if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
- return g_strconcat (dir, G_DIR_SEPARATOR_S, file, (const char*)NULL);
- else
- return g_strconcat (dir, file, (const char*)NULL);
- }
- #ifdef ENABLE_NETCORE
- static MonoReflectionAssemblyHandle
- try_resource_resolve_name (MonoReflectionAssemblyHandle assembly_handle, MonoStringHandle name_handle)
- {
- MonoObjectHandle ret;
- ERROR_DECL (error);
- HANDLE_FUNCTION_ENTER ();
- if (mono_runtime_get_no_exec ())
- goto return_null;
- MONO_STATIC_POINTER_INIT (MonoMethod, resolve_method)
- static gboolean inited;
- if (!inited) {
- MonoClass *alc_class = mono_class_get_assembly_load_context_class ();
- g_assert (alc_class);
- resolve_method = mono_class_get_method_from_name_checked (alc_class, "OnResourceResolve", -1, 0, error);
- inited = TRUE;
- }
- mono_error_cleanup (error);
- error_init_reuse (error);
- MONO_STATIC_POINTER_INIT_END (MonoMethod, resolve_method)
- if (!resolve_method)
- goto return_null;
- gpointer args [2];
- args [0] = MONO_HANDLE_RAW (assembly_handle);
- args [1] = MONO_HANDLE_RAW (name_handle);
- ret = mono_runtime_try_invoke_handle (resolve_method, NULL_HANDLE, args, error);
- goto_if_nok (error, return_null);
- goto exit;
- return_null:
- ret = NULL_HANDLE;
- exit:
- HANDLE_FUNCTION_RETURN_REF (MonoReflectionAssembly, MONO_HANDLE_CAST (MonoReflectionAssembly, ret));
- }
- #endif
- static void *
- get_manifest_resource_internal (MonoReflectionAssemblyHandle assembly_h, MonoStringHandle name, gint32 *size, MonoReflectionModuleHandleOut ref_module, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly_h);
- MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
- MonoTableInfo *table = &assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
- guint32 i;
- guint32 cols [MONO_MANIFEST_SIZE];
- guint32 impl, file_idx;
- const char *val;
- MonoImage *module;
- char *n = mono_string_handle_to_utf8 (name, error);
- return_val_if_nok (error, NULL);
- for (i = 0; i < table->rows; ++i) {
- mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
- val = mono_metadata_string_heap (assembly->image, cols [MONO_MANIFEST_NAME]);
- if (strcmp (val, n) == 0)
- break;
- }
- g_free (n);
- if (i == table->rows)
- return NULL;
- /* FIXME */
- impl = cols [MONO_MANIFEST_IMPLEMENTATION];
- if (impl) {
- /*
- * this code should only be called after obtaining the
- * ResourceInfo and handling the other cases.
- */
- g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
- file_idx = impl >> MONO_IMPLEMENTATION_BITS;
- module = mono_image_load_file_for_image_checked (assembly->image, file_idx, error);
- if (!is_ok (error) || !module)
- return NULL;
- }
- else
- module = assembly->image;
-
- MonoReflectionModuleHandle rm = mono_module_get_object_handle (domain, module, error);
- return_val_if_nok (error, NULL);
- MONO_HANDLE_ASSIGN (ref_module, rm);
- return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
- }
- void *
- ves_icall_System_Reflection_RuntimeAssembly_GetManifestResourceInternal (MonoReflectionAssemblyHandle assembly_h, MonoStringHandle name, gint32 *size, MonoReflectionModuleHandleOut ref_module, MonoError *error)
- {
- gpointer ret = get_manifest_resource_internal (assembly_h, name, size, ref_module, error);
- #ifdef ENABLE_NETCORE
- if (!ret) {
- MonoReflectionAssemblyHandle event_assembly_h = try_resource_resolve_name (assembly_h, name);
- if (MONO_HANDLE_BOOL (event_assembly_h))
- ret = get_manifest_resource_internal (event_assembly_h, name, size, ref_module, error);
- }
- #endif
- return ret;
- }
- static gboolean
- get_manifest_resource_info_internal (MonoReflectionAssemblyHandle assembly_h, MonoStringHandle name, MonoManifestResourceInfoHandle info, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly_h);
- MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
- MonoTableInfo *table = &assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
- int i;
- guint32 cols [MONO_MANIFEST_SIZE];
- guint32 file_cols [MONO_FILE_SIZE];
- const char *val;
- char *n;
- gboolean result = FALSE;
-
- n = mono_string_handle_to_utf8 (name, error);
- goto_if_nok (error, leave);
- for (i = 0; i < table->rows; ++i) {
- mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
- val = mono_metadata_string_heap (assembly->image, cols [MONO_MANIFEST_NAME]);
- if (strcmp (val, n) == 0)
- break;
- }
- g_free (n);
- if (i == table->rows)
- goto leave;
- if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
- MONO_HANDLE_SETVAL (info, location, guint32, RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST);
- }
- else {
- switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
- case MONO_IMPLEMENTATION_FILE:
- i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
- table = &assembly->image->tables [MONO_TABLE_FILE];
- mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
- val = mono_metadata_string_heap (assembly->image, file_cols [MONO_FILE_NAME]);
- MONO_HANDLE_SET (info, filename, mono_string_new_handle (domain, val, error));
- if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
- MONO_HANDLE_SETVAL (info, location, guint32, 0);
- else
- MONO_HANDLE_SETVAL (info, location, guint32, RESOURCE_LOCATION_EMBEDDED);
- break;
- case MONO_IMPLEMENTATION_ASSEMBLYREF:
- i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
- mono_assembly_load_reference (assembly->image, i - 1);
- if (assembly->image->references [i - 1] == REFERENCE_MISSING) {
- mono_error_set_file_not_found (error, NULL, "Assembly %d referenced from assembly %s not found ", i - 1, assembly->image->name);
- goto leave;
- }
- MonoReflectionAssemblyHandle assm_obj;
- assm_obj = mono_assembly_get_object_handle (mono_domain_get (), assembly->image->references [i - 1], error);
- goto_if_nok (error, leave);
- MONO_HANDLE_SET (info, assembly, assm_obj);
- /* Obtain info recursively */
- get_manifest_resource_info_internal (assm_obj, name, info, error);
- goto_if_nok (error, leave);
- guint32 location;
- location = MONO_HANDLE_GETVAL (info, location);
- location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
- MONO_HANDLE_SETVAL (info, location, guint32, location);
- break;
- case MONO_IMPLEMENTATION_EXP_TYPE:
- g_assert_not_reached ();
- break;
- }
- }
- result = TRUE;
- leave:
- HANDLE_FUNCTION_RETURN_VAL (result);
- }
- MonoBoolean
- ves_icall_System_Reflection_RuntimeAssembly_GetManifestResourceInfoInternal (MonoReflectionAssemblyHandle assembly_h, MonoStringHandle name, MonoManifestResourceInfoHandle info_h, MonoError *error)
- {
- return get_manifest_resource_info_internal (assembly_h, name, info_h, error);
- }
- static gboolean
- add_filename_to_files_array (MonoDomain *domain, MonoAssembly * assembly, MonoTableInfo *table, int i, MonoArrayHandle dest, int dest_idx, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER();
- const char *val = mono_metadata_string_heap (assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
- char *n = g_concat_dir_and_file (assembly->basedir, val);
- MonoStringHandle str = mono_string_new_handle (domain, n, error);
- g_free (n);
- goto_if_nok (error, leave);
- MONO_HANDLE_ARRAY_SETREF (dest, dest_idx, str);
- leave:
- HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
- }
- MonoObjectHandle
- ves_icall_System_Reflection_RuntimeAssembly_GetFilesInternal (MonoReflectionAssemblyHandle assembly_h, MonoStringHandle name, MonoBoolean resource_modules, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly_h);
- MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
- MonoTableInfo *table = &assembly->image->tables [MONO_TABLE_FILE];
- int i, count;
- /* check hash if needed */
- if (!MONO_HANDLE_IS_NULL(name)) {
- char *n = mono_string_handle_to_utf8 (name, error);
- goto_if_nok (error, fail);
- for (i = 0; i < table->rows; ++i) {
- const char *val = mono_metadata_string_heap (assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
- if (strcmp (val, n) == 0) {
- g_free (n);
- n = g_concat_dir_and_file (assembly->basedir, val);
- MonoStringHandle fn = mono_string_new_handle (domain, n, error);
- g_free (n);
- goto_if_nok (error, fail);
- return MONO_HANDLE_CAST (MonoObject, fn);
- }
- }
- g_free (n);
- return NULL_HANDLE;
- }
- count = 0;
- for (i = 0; i < table->rows; ++i) {
- if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
- count ++;
- }
- MonoArrayHandle result;
- result = mono_array_new_handle (domain, mono_defaults.string_class, count, error);
- goto_if_nok (error, fail);
- count = 0;
- for (i = 0; i < table->rows; ++i) {
- if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
- if (!add_filename_to_files_array (domain, assembly, table, i, result, count, error))
- goto fail;
- count++;
- }
- }
- return MONO_HANDLE_CAST (MonoObject, result);
- fail:
- return NULL_HANDLE;
- }
- static gboolean
- add_module_to_modules_array (MonoDomain *domain, MonoArrayHandle dest, int *dest_idx, MonoImage* module, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- error_init (error);
- if (module) {
- MonoReflectionModuleHandle rm = mono_module_get_object_handle (domain, module, error);
- goto_if_nok (error, leave);
-
- MONO_HANDLE_ARRAY_SETREF (dest, *dest_idx, rm);
- ++(*dest_idx);
- }
- leave:
- HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
- }
- static gboolean
- add_file_to_modules_array (MonoDomain *domain, MonoArrayHandle dest, int dest_idx, MonoImage *image, MonoTableInfo *table, int table_idx, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- guint32 cols [MONO_FILE_SIZE];
- mono_metadata_decode_row (table, table_idx, cols, MONO_FILE_SIZE);
- if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
- MonoReflectionModuleHandle rm = mono_module_file_get_object_handle (domain, image, table_idx, error);
- goto_if_nok (error, leave);
- MONO_HANDLE_ARRAY_SETREF (dest, dest_idx, rm);
- } else {
- MonoImage *m = mono_image_load_file_for_image_checked (image, table_idx + 1, error);
- goto_if_nok (error, leave);
- if (!m) {
- const char *filename = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
- gboolean refonly = FALSE;
- if (image->assembly)
- refonly = mono_asmctx_get_kind (&image->assembly->context) == MONO_ASMCTX_REFONLY;
- mono_error_set_simple_file_not_found (error, filename, refonly);
- goto leave;
- }
- MonoReflectionModuleHandle rm = mono_module_get_object_handle (domain, m, error);
- goto_if_nok (error, leave);
- MONO_HANDLE_ARRAY_SETREF (dest, dest_idx, rm);
- }
- leave:
- HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
- }
- MonoArrayHandle
- ves_icall_System_Reflection_RuntimeAssembly_GetModulesInternal (MonoReflectionAssemblyHandle assembly_h, MonoError *error)
- {
- error_init (error);
- MonoDomain *domain = mono_domain_get();
- MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
- MonoClass *klass;
- int i, j, file_count = 0;
- MonoImage **modules;
- guint32 module_count, real_module_count;
- MonoTableInfo *table;
- MonoImage *image = assembly->image;
- g_assert (image != NULL);
- g_assert (!assembly_is_dynamic (assembly));
- table = &image->tables [MONO_TABLE_FILE];
- file_count = table->rows;
- modules = image->modules;
- module_count = image->module_count;
- real_module_count = 0;
- for (i = 0; i < module_count; ++i)
- if (modules [i])
- real_module_count ++;
- klass = mono_class_get_module_class ();
- MonoArrayHandle res = mono_array_new_handle (domain, klass, 1 + real_module_count + file_count, error);
- goto_if_nok (error, fail);
- MonoReflectionModuleHandle image_obj;
- image_obj = mono_module_get_object_handle (domain, image, error);
- goto_if_nok (error, fail);
- MONO_HANDLE_ARRAY_SETREF (res, 0, image_obj);
- j = 1;
- for (i = 0; i < module_count; ++i)
- if (!add_module_to_modules_array (domain, res, &j, modules[i], error))
- goto fail;
- for (i = 0; i < file_count; ++i, ++j) {
- if (!add_file_to_modules_array (domain, res, j, image, table, i, error))
- goto fail;
- }
- return res;
- fail:
- return NULL_HANDLE_ARRAY;
- }
- MonoReflectionMethodHandle
- ves_icall_GetCurrentMethod (MonoError *error)
- {
- MonoMethod *m = mono_method_get_last_managed ();
- if (!m) {
- mono_error_set_not_supported (error, "Stack walks are not supported on this platform.");
- return MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
- }
- while (m->is_inflated)
- m = ((MonoMethodInflated*)m)->declaring;
- return mono_method_get_object_handle (mono_domain_get (), m, NULL, error);
- }
- static MonoMethod*
- mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
- {
- int offset = -1, i;
- if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
- ERROR_DECL (error);
- MonoMethod *result;
- MonoMethodInflated *inflated = (MonoMethodInflated*)method;
- //method is inflated, we should inflate it on the other class
- MonoGenericContext ctx;
- ctx.method_inst = inflated->context.method_inst;
- ctx.class_inst = inflated->context.class_inst;
- if (mono_class_is_ginst (klass))
- ctx.class_inst = mono_class_get_generic_class (klass)->context.class_inst;
- else if (mono_class_is_gtd (klass))
- ctx.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
- result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, error);
- g_assert (is_ok (error)); /* FIXME don't swallow the error */
- return result;
- }
- mono_class_setup_methods (method->klass);
- if (mono_class_has_failure (method->klass))
- return NULL;
- int mcount = mono_class_get_method_count (method->klass);
- MonoMethod **method_klass_methods = m_class_get_methods (method->klass);
- for (i = 0; i < mcount; ++i) {
- if (method_klass_methods [i] == method) {
- offset = i;
- break;
- }
- }
- mono_class_setup_methods (klass);
- if (mono_class_has_failure (klass))
- return NULL;
- g_assert (offset >= 0 && offset < mono_class_get_method_count (klass));
- return m_class_get_methods (klass) [offset];
- }
- MonoReflectionMethodHandle
- ves_icall_System_Reflection_RuntimeMethodInfo_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check, MonoError *error)
- {
- MonoClass *klass;
- if (type && generic_check) {
- klass = mono_class_from_mono_type_internal (type);
- if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
- return MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
- if (method->klass != klass) {
- method = mono_method_get_equivalent_method (method, klass);
- if (!method)
- return MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
- }
- } else if (type)
- klass = mono_class_from_mono_type_internal (type);
- else
- klass = method->klass;
- return mono_method_get_object_handle (mono_domain_get (), method, klass, error);
- }
- MonoReflectionMethodBodyHandle
- ves_icall_System_Reflection_RuntimeMethodInfo_GetMethodBodyInternal (MonoMethod *method, MonoError *error)
- {
- return mono_method_body_get_object_handle (mono_domain_get (), method, error);
- }
- #if ENABLE_NETCORE
- MonoReflectionAssemblyHandle
- ves_icall_System_Reflection_Assembly_GetExecutingAssembly (MonoStackCrawlMark *stack_mark, MonoError *error)
- {
- MonoAssembly *assembly;
- assembly = mono_runtime_get_caller_from_stack_mark (stack_mark);
- g_assert (assembly);
- return mono_assembly_get_object_handle (mono_domain_get (), assembly, error);
- }
- #else
- MonoReflectionAssemblyHandle
- ves_icall_System_Reflection_Assembly_GetExecutingAssembly (MonoError *error)
- {
- MonoMethod *dest = NULL;
- mono_stack_walk_no_il (get_executing, &dest);
- g_assert (dest);
- return mono_assembly_get_object_handle (mono_domain_get (), m_class_get_image (dest->klass)->assembly, error);
- }
- #endif
- MonoReflectionAssemblyHandle
- ves_icall_System_Reflection_Assembly_GetEntryAssembly (MonoError *error)
- {
- MonoDomain* domain = mono_domain_get ();
- if (!domain->entry_assembly)
- return MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
- return mono_assembly_get_object_handle (domain, domain->entry_assembly, error);
- }
- MonoReflectionAssemblyHandle
- ves_icall_System_Reflection_Assembly_GetCallingAssembly (MonoError *error)
- {
- error_init (error);
- MonoMethod *m;
- MonoMethod *dest;
- dest = NULL;
- mono_stack_walk_no_il (get_executing, &dest);
- m = dest;
- mono_stack_walk_no_il (get_caller_no_reflection, &dest);
- if (!dest)
- dest = m;
- if (!m) {
- mono_error_set_not_supported (error, "Stack walks are not supported on this platform.");
- return MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
- }
- return mono_assembly_get_object_handle (mono_domain_get (), m_class_get_image (dest->klass)->assembly, error);
- }
- MonoStringHandle
- ves_icall_System_RuntimeType_getFullName (MonoReflectionTypeHandle object, MonoBoolean full_name,
- MonoBoolean assembly_qualified, MonoError *error)
- {
- MonoDomain *domain = mono_object_domain (MONO_HANDLE_RAW (object));
- MonoType *type = MONO_HANDLE_RAW (object)->type;
- MonoTypeNameFormat format;
- MonoStringHandle res;
- gchar *name;
- if (full_name)
- format = assembly_qualified ?
- MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
- MONO_TYPE_NAME_FORMAT_FULL_NAME;
- else
- format = MONO_TYPE_NAME_FORMAT_REFLECTION;
-
- name = mono_type_get_name_full (type, format);
- if (!name)
- return NULL_HANDLE_STRING;
- if (full_name && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
- g_free (name);
- return NULL_HANDLE_STRING;
- }
- res = mono_string_new_handle (domain, name, error);
- g_free (name);
- return res;
- }
- #ifndef ENABLE_NETCORE
- int
- ves_icall_RuntimeType_get_core_clr_security_level (MonoReflectionTypeHandle rfield, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL (rfield, type);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- mono_class_init_checked (klass, error);
- return_val_if_nok (error, -1);
- return mono_security_core_clr_class_level (klass);
- }
- int
- ves_icall_RuntimeFieldInfo_get_core_clr_security_level (MonoReflectionFieldHandle rfield, MonoError *error)
- {
- MonoClassField *field = MONO_HANDLE_GETVAL (rfield, field);
- return mono_security_core_clr_field_level (field, TRUE);
- }
- int
- ves_icall_RuntimeMethodInfo_get_core_clr_security_level (MonoReflectionMethodHandle rfield, MonoError *error)
- {
- MonoMethod *method = MONO_HANDLE_GETVAL (rfield, method);
- return mono_security_core_clr_method_level (method, TRUE);
- }
- #endif
- MonoStringHandle
- ves_icall_System_Reflection_RuntimeAssembly_get_fullname (MonoReflectionAssemblyHandle assembly, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly);
- MonoAssembly *mass = MONO_HANDLE_GETVAL (assembly, assembly);
- gchar *name;
- name = mono_stringify_assembly_name (&mass->aname);
- MonoStringHandle res = mono_string_new_handle (domain, name, error);
- g_free (name);
- return res;
- }
- MonoAssemblyName *
- ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
- {
- return &mass->aname;
- }
- void
- ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoStringHandle fname, MonoAssemblyName *name, MonoStringHandleOut normalized_codebase, MonoError *error)
- {
- char *filename;
- MonoImageOpenStatus status = MONO_IMAGE_OK;
- char *codebase = NULL;
- gboolean res;
- MonoImage *image;
- char *dirname;
- error_init (error);
- MonoDomain *domain = MONO_HANDLE_DOMAIN (fname);
- filename = mono_string_handle_to_utf8 (fname, error);
- return_if_nok (error);
- dirname = g_path_get_dirname (filename);
- replace_shadow_path (mono_domain_get (), dirname, &filename);
- g_free (dirname);
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "InternalGetAssemblyName (\"%s\")", filename);
- MonoAssemblyLoadContext *alc = mono_domain_default_alc (domain);
- image = mono_image_open_a_lot (alc, filename, &status, TRUE, FALSE);
- if (!image){
- if (status == MONO_IMAGE_IMAGE_INVALID)
- mono_error_set_bad_image_by_name (error, filename, "Invalid Image: %s", filename);
- else
- mono_error_set_simple_file_not_found (error, filename, FALSE);
- g_free (filename);
- return;
- }
- res = mono_assembly_fill_assembly_name_full (image, name, TRUE);
- if (!res) {
- mono_image_close (image);
- g_free (filename);
- mono_error_set_argument (error, "assemblyFile", "The file does not contain a manifest");
- return;
- }
- if (filename != NULL && *filename != '\0') {
- gchar *result;
- codebase = g_strdup (filename);
- mono_icall_make_platform_path (codebase);
- const gchar *prepend = mono_icall_get_file_path_prefix (codebase);
- result = g_strconcat (prepend, codebase, (const char*)NULL);
- g_free (codebase);
- codebase = result;
- }
- MONO_HANDLE_ASSIGN (normalized_codebase, mono_string_new_handle (mono_domain_get (), codebase, error));
- g_free (codebase);
- mono_image_close (image);
- g_free (filename);
- }
- #ifndef ENABLE_NETCORE
- MonoBoolean
- ves_icall_System_Reflection_RuntimeAssembly_LoadPermissions (MonoReflectionAssemblyHandle assembly_h,
- char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength, MonoError *error)
- {
- MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
- MonoBoolean result = FALSE;
- MonoDeclSecurityEntry entry;
- /* SecurityAction.RequestMinimum */
- if (mono_declsec_get_assembly_action (assembly, SECURITY_ACTION_REQMIN, &entry)) {
- *minimum = entry.blob;
- *minLength = entry.size;
- result = TRUE;
- }
- /* SecurityAction.RequestOptional */
- if (mono_declsec_get_assembly_action (assembly, SECURITY_ACTION_REQOPT, &entry)) {
- *optional = entry.blob;
- *optLength = entry.size;
- result = TRUE;
- }
- /* SecurityAction.RequestRefuse */
- if (mono_declsec_get_assembly_action (assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
- *refused = entry.blob;
- *refLength = entry.size;
- result = TRUE;
- }
- return result;
- }
- #endif
- static gboolean
- mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
- {
- guint32 attrs, visibility;
- do {
- attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
- visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
- if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
- return FALSE;
- } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
- return TRUE;
- }
- static void
- image_get_type (MonoDomain *domain, MonoImage *image, MonoTableInfo *tdef, int table_idx, int count, MonoArrayHandle res, MonoArrayHandle exceptions, MonoBoolean exportedOnly, MonoError *error)
- {
- error_init (error);
- HANDLE_FUNCTION_ENTER ();
- ERROR_DECL (klass_error);
- MonoClass *klass = mono_class_get_checked (image, table_idx | MONO_TOKEN_TYPE_DEF, klass_error);
- if (klass) {
- MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
- return_if_nok (error);
- MONO_HANDLE_ARRAY_SETREF (res, count, rt);
- } else {
- MonoExceptionHandle ex = mono_error_convert_to_exception_handle (klass_error);
- MONO_HANDLE_ARRAY_SETREF (exceptions, count, ex);
- }
- HANDLE_FUNCTION_RETURN ();
- }
- static MonoArrayHandle
- mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArrayHandleOut exceptions, MonoBoolean exportedOnly, MonoError *error)
- {
- MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
- int i, count;
- error_init (error);
- /* we start the count from 1 because we skip the special type <Module> */
- if (exportedOnly) {
- count = 0;
- for (i = 1; i < tdef->rows; ++i) {
- if (mono_module_type_is_visible (tdef, image, i + 1))
- count++;
- }
- } else {
- count = tdef->rows - 1;
- }
- MonoArrayHandle res = mono_array_new_handle (domain, mono_defaults.runtimetype_class, count, error);
- return_val_if_nok (error, NULL_HANDLE_ARRAY);
- MONO_HANDLE_ASSIGN (exceptions, mono_array_new_handle (domain, mono_defaults.exception_class, count, error));
- return_val_if_nok (error, NULL_HANDLE_ARRAY);
- count = 0;
- for (i = 1; i < tdef->rows; ++i) {
- if (!exportedOnly || mono_module_type_is_visible (tdef, image, i+1)) {
- image_get_type (domain, image, tdef, i + 1, count, res, exceptions, exportedOnly, error);
- return_val_if_nok (error, NULL_HANDLE_ARRAY);
- count++;
- }
- }
-
- return res;
- }
- static void
- append_module_types (MonoDomain *domain, MonoArrayHandleOut res, MonoArrayHandleOut exceptions, MonoImage *image, MonoBoolean exportedOnly, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- error_init (error);
- MonoArrayHandle ex2 = MONO_HANDLE_NEW (MonoArray, NULL);
- MonoArrayHandle res2 = mono_module_get_types (domain, image, ex2, exportedOnly, error);
- goto_if_nok (error, leave);
- /* Append the new types to the end of the array */
- if (mono_array_handle_length (res2) > 0) {
- guint32 len1, len2;
- len1 = mono_array_handle_length (res);
- len2 = mono_array_handle_length (res2);
- MonoArrayHandle res3 = mono_array_new_handle (domain, mono_defaults.runtimetype_class, len1 + len2, error);
- goto_if_nok (error, leave);
- mono_array_handle_memcpy_refs (res3, 0, res, 0, len1);
- mono_array_handle_memcpy_refs (res3, len1, res2, 0, len2);
- MONO_HANDLE_ASSIGN (res, res3);
- MonoArrayHandle ex3 = mono_array_new_handle (domain, mono_defaults.runtimetype_class, len1 + len2, error);
- goto_if_nok (error, leave);
- mono_array_handle_memcpy_refs (ex3, 0, exceptions, 0, len1);
- mono_array_handle_memcpy_refs (ex3, len1, ex2, 0, len2);
- MONO_HANDLE_ASSIGN (exceptions, ex3);
- }
- leave:
- HANDLE_FUNCTION_RETURN ();
- }
- static void
- set_class_failure_in_array (MonoArrayHandle exl, int i, MonoClass *klass)
- {
- HANDLE_FUNCTION_ENTER ();
- ERROR_DECL (unboxed_error);
- mono_error_set_for_class_failure (unboxed_error, klass);
- MonoExceptionHandle exc = MONO_HANDLE_NEW (MonoException, mono_error_convert_to_exception (unboxed_error));
- MONO_HANDLE_ARRAY_SETREF (exl, i, exc);
- HANDLE_FUNCTION_RETURN ();
- }
- static MonoArrayHandle
- assembly_get_types (MonoReflectionAssemblyHandle assembly_handle, MonoBoolean exportedOnly, MonoError *error)
- {
- MonoArrayHandle exceptions = MONO_HANDLE_NEW(MonoArray, NULL);
- int i;
- MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly_handle);
- MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_handle, assembly);
- g_assert (!assembly_is_dynamic (assembly));
- MonoImage *image = assembly->image;
- MonoTableInfo *table = &image->tables [MONO_TABLE_FILE];
- MonoArrayHandle res = mono_module_get_types (domain, image, exceptions, exportedOnly, error);
- return_val_if_nok (error, NULL_HANDLE_ARRAY);
- /* Append data from all modules in the assembly */
- for (i = 0; i < table->rows; ++i) {
- if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
- MonoImage *loaded_image = mono_assembly_load_module_checked (image->assembly, i + 1, error);
- return_val_if_nok (error, NULL_HANDLE_ARRAY);
- if (loaded_image) {
- append_module_types (domain, res, exceptions, loaded_image, exportedOnly, error);
- return_val_if_nok (error, NULL_HANDLE_ARRAY);
- }
- }
- }
- /* the ReflectionTypeLoadException must have all the types (Types property),
- * NULL replacing types which throws an exception. The LoaderException must
- * contain all exceptions for NULL items.
- */
- int len = mono_array_handle_length (res);
- int ex_count = 0;
- GList *list = NULL;
- MonoReflectionTypeHandle t = MONO_HANDLE_NEW (MonoReflectionType, NULL);
- for (i = 0; i < len; i++) {
- MONO_HANDLE_ARRAY_GETREF (t, res, i);
- if (!MONO_HANDLE_IS_NULL (t)) {
- MonoClass *klass = mono_type_get_class_internal (MONO_HANDLE_GETVAL (t, type));
- if ((klass != NULL) && mono_class_has_failure (klass)) {
- /* keep the class in the list */
- list = g_list_append (list, klass);
- /* and replace Type with NULL */
- MONO_HANDLE_ARRAY_SETREF (res, i, NULL_HANDLE);
- }
- } else {
- ex_count ++;
- }
- }
- if (list || ex_count) {
- GList *tmp = NULL;
- int j, length = g_list_length (list) + ex_count;
- MonoArrayHandle exl = mono_array_new_handle (domain, mono_defaults.exception_class, length, error);
- if (!is_ok (error)) {
- g_list_free (list);
- return NULL_HANDLE_ARRAY;
- }
- /* Types for which mono_class_get_checked () succeeded */
- MonoExceptionHandle exc = MONO_HANDLE_NEW (MonoException, NULL);
- for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
- set_class_failure_in_array (exl, i, (MonoClass*)tmp->data);
- }
- /* Types for which it don't */
- for (j = 0; j < mono_array_handle_length (exceptions); ++j) {
- MONO_HANDLE_ARRAY_GETREF (exc, exceptions, j);
- if (!MONO_HANDLE_IS_NULL (exc)) {
- g_assert (i < length);
- MONO_HANDLE_ARRAY_SETREF (exl, i, exc);
- i ++;
- }
- }
- g_list_free (list);
- list = NULL;
- MONO_HANDLE_ASSIGN (exc, mono_get_exception_reflection_type_load_checked (res, exl, error));
- return_val_if_nok (error, NULL_HANDLE_ARRAY);
- mono_error_set_exception_handle (error, exc);
- return NULL_HANDLE_ARRAY;
- }
-
- return res;
- }
- #ifndef ENABLE_NETCORE
- MonoArrayHandle
- ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssemblyHandle assembly_handle, MonoBoolean exportedOnly, MonoError *error)
- {
- return assembly_get_types (assembly_handle, exportedOnly, error);
- }
- #endif
- #if ENABLE_NETCORE
- MonoArrayHandle
- ves_icall_System_Reflection_RuntimeAssembly_GetExportedTypes (MonoReflectionAssemblyHandle assembly_handle, MonoError *error)
- {
- return assembly_get_types (assembly_handle, TRUE, error);
- }
- static void
- get_top_level_forwarded_type (MonoImage *image, MonoTableInfo *table, int i, MonoArrayHandle types, MonoArrayHandle exceptions, int *aindex, int *exception_count)
- {
- ERROR_DECL (local_error);
- guint32 cols [MONO_EXP_TYPE_SIZE];
- MonoClass *klass;
- MonoReflectionTypeHandle rt;
-
- mono_metadata_decode_row (table, i, cols, MONO_EXP_TYPE_SIZE);
- if (!(cols [MONO_EXP_TYPE_FLAGS] & TYPE_ATTRIBUTE_FORWARDER))
- return;
- guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
- const char *name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
- const char *nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
- g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF);
- guint32 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
- mono_assembly_load_reference (image, assembly_idx - 1);
- g_assert (image->references [assembly_idx - 1]);
- HANDLE_FUNCTION_ENTER ();
- if (image->references [assembly_idx - 1] == REFERENCE_MISSING) {
- MonoExceptionHandle ex = MONO_HANDLE_NEW (MonoException, mono_get_exception_bad_image_format ("Invalid image"));
- MONO_HANDLE_ARRAY_SETREF (types, *aindex, NULL_HANDLE);
- MONO_HANDLE_ARRAY_SETREF (exceptions, *aindex, ex);
- (*exception_count)++; (*aindex)++;
- goto exit;
- }
- klass = mono_class_from_name_checked (image->references [assembly_idx - 1]->image, nspace, name, local_error);
- if (!is_ok (local_error)) {
- MonoExceptionHandle ex = mono_error_convert_to_exception_handle (local_error);
- MONO_HANDLE_ARRAY_SETREF (types, *aindex, NULL_HANDLE);
- MONO_HANDLE_ARRAY_SETREF (exceptions, *aindex, ex);
- mono_error_cleanup (local_error);
- (*exception_count)++; (*aindex)++;
- goto exit;
- }
- rt = mono_type_get_object_handle (mono_domain_get (), m_class_get_byval_arg (klass), local_error);
- if (!is_ok (local_error)) {
- MonoExceptionHandle ex = mono_error_convert_to_exception_handle (local_error);
- MONO_HANDLE_ARRAY_SETREF (types, *aindex, NULL_HANDLE);
- MONO_HANDLE_ARRAY_SETREF (exceptions, *aindex, ex);
- mono_error_cleanup (local_error);
- (*exception_count)++; (*aindex)++;
- goto exit;
- }
- MONO_HANDLE_ARRAY_SETREF (types, *aindex, rt);
- MONO_HANDLE_ARRAY_SETREF (exceptions, *aindex, NULL_HANDLE);
- (*aindex)++;
- exit:
- HANDLE_FUNCTION_RETURN ();
- }
- MonoArrayHandle
- ves_icall_System_Reflection_RuntimeAssembly_GetTopLevelForwardedTypes (MonoReflectionAssemblyHandle assembly_h, MonoError *error)
- {
- MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
- MonoImage *image = assembly->image;
- int count = 0;
- g_assert (!assembly_is_dynamic (assembly));
- MonoTableInfo *table = &image->tables [MONO_TABLE_EXPORTEDTYPE];
- for (int i = 0; i < table->rows; ++i) {
- if (mono_metadata_decode_row_col (table, i, MONO_EXP_TYPE_FLAGS) & TYPE_ATTRIBUTE_FORWARDER)
- count ++;
- }
-
- MonoArrayHandle types = mono_array_new_handle (mono_domain_get (), mono_defaults.runtimetype_class, count, error);
- return_val_if_nok (error, NULL_HANDLE_ARRAY);
- MonoArrayHandle exceptions = mono_array_new_handle (mono_domain_get (), mono_defaults.exception_class, count, error);
- return_val_if_nok (error, NULL_HANDLE_ARRAY);
- int aindex = 0;
- int exception_count = 0;
- for (int i = 0; i < table->rows; ++i) {
- get_top_level_forwarded_type (image, table, i, types, exceptions, &aindex, &exception_count);
- }
- if (exception_count > 0) {
- MonoExceptionHandle exc = MONO_HANDLE_NEW (MonoException, NULL);
- MONO_HANDLE_ASSIGN (exc, mono_get_exception_reflection_type_load_checked (types, exceptions, error));
- return_val_if_nok (error, NULL_HANDLE_ARRAY);
- mono_error_set_exception_handle (error, exc);
- return NULL_HANDLE_ARRAY;
- }
- return types;
- }
- #endif
- void
- ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname, MonoBoolean free_struct)
- {
- mono_assembly_name_free_internal (aname);
- if (free_struct)
- g_free (aname);
- }
- void
- ves_icall_Mono_Runtime_DisableMicrosoftTelemetry (void)
- {
- #if defined(TARGET_OSX) && !defined(DISABLE_CRASH_REPORTING)
- mono_merp_disable ();
- #else
- // Icall has platform check in managed too.
- g_assert_not_reached ();
- #endif
- }
- void
- ves_icall_Mono_Runtime_AnnotateMicrosoftTelemetry (const char *key, const char *value)
- {
- #if defined(TARGET_OSX) && !defined(DISABLE_CRASH_REPORTING)
- if (!mono_merp_enabled ())
- g_error ("Cannot add attributes to telemetry without enabling subsystem");
- mono_merp_add_annotation (key, value);
- #else
- // Icall has platform check in managed too.
- g_assert_not_reached ();
- #endif
- }
- void
- ves_icall_Mono_Runtime_EnableMicrosoftTelemetry (const char *appBundleID, const char *appSignature, const char *appVersion, const char *merpGUIPath, const char *appPath, const char *configDir, MonoError *error)
- {
- #if defined(TARGET_OSX) && !defined(DISABLE_CRASH_REPORTING)
- mono_merp_enable (appBundleID, appSignature, appVersion, merpGUIPath, appPath, configDir);
- mono_get_runtime_callbacks ()->install_state_summarizer ();
- #else
- // Icall has platform check in managed too.
- g_assert_not_reached ();
- #endif
- }
- // Number derived from trials on relevant hardware.
- // If it seems large, please confirm it's safe to shrink
- // before doing so.
- #define MONO_MAX_SUMMARY_LEN_ICALL 500000
- MonoStringHandle
- ves_icall_Mono_Runtime_ExceptionToState (MonoExceptionHandle exc_handle, guint64 *portable_hash_out, guint64 *unportable_hash_out, MonoError *error)
- {
- MonoStringHandle result;
- #ifndef DISABLE_CRASH_REPORTING
- if (mono_get_eh_callbacks ()->mono_summarize_exception) {
- // FIXME: Push handles down into mini/mini-exceptions.c
- MonoException *exc = MONO_HANDLE_RAW (exc_handle);
- MonoThreadSummary out;
- mono_summarize_timeline_start ("ExceptionToState");
- mono_summarize_timeline_phase_log (MonoSummarySuspendHandshake);
- mono_summarize_timeline_phase_log (MonoSummaryUnmanagedStacks);
- mono_get_eh_callbacks ()->mono_summarize_exception (exc, &out);
- mono_summarize_timeline_phase_log (MonoSummaryManagedStacks);
- *portable_hash_out = (guint64) out.hashes.offset_free_hash;
- *unportable_hash_out = (guint64) out.hashes.offset_rich_hash;
- MonoStateWriter writer;
- char *scratch = g_new0 (gchar, MONO_MAX_SUMMARY_LEN_ICALL);
- mono_state_writer_init (&writer, scratch, MONO_MAX_SUMMARY_LEN_ICALL);
- mono_native_state_init (&writer);
- mono_summarize_timeline_phase_log (MonoSummaryStateWriter);
- gboolean first_thread_added = TRUE;
- mono_native_state_add_thread (&writer, &out, NULL, first_thread_added, TRUE);
- char *output = mono_native_state_free (&writer, FALSE);
- mono_summarize_timeline_phase_log (MonoSummaryStateWriterDone);
- result = mono_string_new_handle (mono_domain_get (), output, error);
- g_free (output);
- g_free (scratch);
- return result;
- }
- #endif
- *portable_hash_out = 0;
- *unportable_hash_out = 0;
- result = mono_string_new_handle (mono_domain_get (), "", error);
- return result;
- }
- void
- ves_icall_Mono_Runtime_SendMicrosoftTelemetry (const char *payload, guint64 portable_hash, guint64 unportable_hash, MonoError *error)
- {
- #if defined(TARGET_OSX) && !defined(DISABLE_CRASH_REPORTING)
- if (!mono_merp_enabled ())
- g_error ("Cannot send telemetry without registering parameters first");
- pid_t crashed_pid = getpid ();
- MonoStackHash hashes;
- memset (&hashes, 0, sizeof (MonoStackHash));
- hashes.offset_free_hash = portable_hash;
- hashes.offset_rich_hash = unportable_hash;
- const char *signal = "MANAGED_EXCEPTION";
- gboolean success = mono_merp_invoke (crashed_pid, signal, payload, &hashes);
- if (!success) {
- //g_assert_not_reached ();
- mono_error_set_generic_error (error, "System", "Exception", "We were unable to start the Microsoft Error Reporting client.");
- }
- #else
- // Icall has platform check in managed too.
- g_assert_not_reached ();
- #endif
- }
- void
- ves_icall_Mono_Runtime_DumpTelemetry (const char *payload, guint64 portable_hash, guint64 unportable_hash, MonoError *error)
- {
- #ifndef DISABLE_CRASH_REPORTING
- MonoStackHash hashes;
- memset (&hashes, 0, sizeof (MonoStackHash));
- hashes.offset_free_hash = portable_hash;
- hashes.offset_rich_hash = unportable_hash;
- mono_crash_dump (payload, &hashes);
- #else
- return;
- #endif
- }
- MonoStringHandle
- ves_icall_Mono_Runtime_DumpStateSingle (guint64 *portable_hash, guint64 *unportable_hash, MonoError *error)
- {
- MonoStringHandle result;
- #ifndef DISABLE_CRASH_REPORTING
- MonoStackHash hashes;
- memset (&hashes, 0, sizeof (MonoStackHash));
- MonoContext *ctx = NULL;
- MonoThreadSummary this_thread;
- if (!mono_threads_summarize_one (&this_thread, ctx))
- return mono_string_new_handle (mono_domain_get (), "", error);
- *portable_hash = (guint64) this_thread.hashes.offset_free_hash;
- *unportable_hash = (guint64) this_thread.hashes.offset_rich_hash;
- MonoStateWriter writer;
- char *scratch = g_new0 (gchar, MONO_MAX_SUMMARY_LEN_ICALL);
- mono_state_writer_init (&writer, scratch, MONO_MAX_SUMMARY_LEN_ICALL);
- mono_native_state_init (&writer);
- gboolean first_thread_added = TRUE;
- mono_native_state_add_thread (&writer, &this_thread, NULL, first_thread_added, TRUE);
- char *output = mono_native_state_free (&writer, FALSE);
- result = mono_string_new_handle (mono_domain_get (), output, error);
- g_free (output);
- g_free (scratch);
- #else
- *portable_hash = 0;
- *unportable_hash = 0;
- result = mono_string_new_handle (mono_domain_get (), "", error);
- #endif
- return result;
- }
- void
- ves_icall_Mono_Runtime_RegisterReportingForNativeLib (const char *path_suffix, const char *module_name)
- {
- #ifndef DISABLE_CRASH_REPORTING
- if (mono_get_eh_callbacks ()->mono_register_native_library)
- mono_get_eh_callbacks ()->mono_register_native_library (path_suffix, module_name);
- #endif
- }
- void
- ves_icall_Mono_Runtime_RegisterReportingForAllNativeLibs ()
- {
- #ifndef DISABLE_CRASH_REPORTING
- if (mono_get_eh_callbacks ()->mono_allow_all_native_libraries)
- mono_get_eh_callbacks ()->mono_allow_all_native_libraries ();
- #endif
- }
- void
- ves_icall_Mono_Runtime_EnableCrashReportingLog (const char *directory)
- {
- #ifndef DISABLE_CRASH_REPORTING
- mono_summarize_set_timeline_dir (directory);
- #endif
- }
- int
- ves_icall_Mono_Runtime_CheckCrashReportingLog (const char *directory, MonoBoolean clear)
- {
- int ret = 0;
- #ifndef DISABLE_CRASH_REPORTING
- ret = (int) mono_summarize_timeline_read_level (directory, clear != 0);
- #endif
- return ret;
- }
- MonoStringHandle
- ves_icall_Mono_Runtime_DumpStateTotal (guint64 *portable_hash, guint64 *unportable_hash, MonoError *error)
- {
- MonoStringHandle result;
- #ifndef DISABLE_CRASH_REPORTING
- char *scratch = g_new0 (gchar, MONO_MAX_SUMMARY_LEN_ICALL);
- char *out;
- MonoStackHash hashes;
- memset (&hashes, 0, sizeof (MonoStackHash));
- MonoContext *ctx = NULL;
- while (!mono_dump_start ())
- g_usleep (1000); // wait around for other dump to finish
- mono_get_runtime_callbacks ()->install_state_summarizer ();
- mono_summarize_timeline_start ("DumpStateTotal");
- gboolean success = mono_threads_summarize (ctx, &out, &hashes, TRUE, FALSE, scratch, MONO_MAX_SUMMARY_LEN_ICALL);
- mono_summarize_timeline_phase_log (MonoSummaryCleanup);
- if (!success)
- return mono_string_new_handle (mono_domain_get (), "", error);
- *portable_hash = (guint64) hashes.offset_free_hash;
- *unportable_hash = (guint64) hashes.offset_rich_hash;
- result = mono_string_new_handle (mono_domain_get (), out, error);
- // out is now a pointer into garbage memory
- g_free (scratch);
- mono_summarize_timeline_phase_log (MonoSummaryDone);
- mono_dump_complete ();
- #else
- *portable_hash = 0;
- *unportable_hash = 0;
- result = mono_string_new_handle (mono_domain_get (), "", error);
- #endif
- return result;
- }
- #if defined (ENABLE_NETCORE) && defined (ENABLE_METADATA_UPDATE)
- void
- ves_icall_Mono_Runtime_LoadMetadataUpdate (MonoAssembly *assm,
- gconstpointer dmeta_bytes, int32_t dmeta_len,
- gconstpointer dil_bytes, int32_t dil_len)
- {
- ERROR_DECL (error);
- g_assert (assm);
- g_assert (dmeta_len >= 0);
- MonoImage *image_base = assm->image;
- g_assert (image_base);
- MonoDomain *domain = mono_domain_get ();
- mono_image_load_enc_delta (domain, image_base, dmeta_bytes, dmeta_len, dil_bytes, dil_len, error);
- mono_error_set_pending_exception (error);
- }
- #endif
- MonoBoolean
- ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, MonoBoolean *is_version_defined_arg, MonoBoolean *is_token_defined_arg)
- {
- gboolean is_version_defined = FALSE;
- gboolean is_token_defined = FALSE;
- gboolean result = FALSE;
- result = mono_assembly_name_parse_full (name, aname, TRUE, &is_version_defined, &is_token_defined);
- *is_version_defined_arg = (MonoBoolean)is_version_defined;
- *is_token_defined_arg = (MonoBoolean)is_token_defined;
- return result;
- }
- MonoReflectionTypeHandle
- ves_icall_System_Reflection_RuntimeModule_GetGlobalType (MonoImage *image, MonoError *error)
- {
- MonoDomain *domain = mono_domain_get ();
- MonoClass *klass;
- g_assert (image);
- MonoReflectionTypeHandle ret = MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
- if (image_is_dynamic (image) && ((MonoDynamicImage*)image)->initial_image)
- /* These images do not have a global type */
- goto leave;
- klass = mono_class_get_checked (image, 1 | MONO_TOKEN_TYPE_DEF, error);
- goto_if_nok (error, leave);
- ret = mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
- leave:
- return ret;
- }
- void
- ves_icall_System_Reflection_RuntimeModule_GetGuidInternal (MonoImage *image, MonoArrayHandle guid_h, MonoError *error)
- {
- g_assert (mono_array_handle_length (guid_h) == 16);
- if (!image->metadata_only) {
- g_assert (image->heap_guid.data);
- g_assert (image->heap_guid.size >= 16);
- MONO_ENTER_NO_SAFEPOINTS;
- guint8 *data = (guint8*) mono_array_addr_with_size_internal (MONO_HANDLE_RAW (guid_h), 1, 0);
- memcpy (data, (guint8*)image->heap_guid.data, 16);
- MONO_EXIT_NO_SAFEPOINTS;
- } else {
- MONO_ENTER_NO_SAFEPOINTS;
- guint8 *data = (guint8*) mono_array_addr_with_size_internal (MONO_HANDLE_RAW (guid_h), 1, 0);
- memset (data, 0, 16);
- MONO_EXIT_NO_SAFEPOINTS;
- }
- }
- #ifndef HOST_WIN32
- static inline gpointer
- mono_icall_module_get_hinstance (MonoImage *image)
- {
- return (gpointer) (-1);
- }
- #endif /* HOST_WIN32 */
- #ifndef ENABLE_NETCORE
- gpointer
- ves_icall_System_Reflection_RuntimeModule_GetHINSTANCE (MonoImage *image, MonoError *error)
- {
- return mono_icall_module_get_hinstance (image);
- }
- #endif
- void
- ves_icall_System_Reflection_RuntimeModule_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine, MonoError *error)
- {
- if (image_is_dynamic (image)) {
- MonoDynamicImage *dyn = (MonoDynamicImage*)image;
- *pe_kind = dyn->pe_kind;
- *machine = dyn->machine;
- }
- else {
- *pe_kind = (image->image_info->cli_cli_header.ch_flags & 0x3);
- *machine = image->image_info->cli_header.coff.coff_machine;
- }
- }
- gint32
- ves_icall_System_Reflection_RuntimeModule_GetMDStreamVersion (MonoImage *image, MonoError *error)
- {
- return (image->md_version_major << 16) | (image->md_version_minor);
- }
- MonoArrayHandle
- ves_icall_System_Reflection_RuntimeModule_InternalGetTypes (MonoImage *image, MonoError *error)
- {
- MonoDomain *domain = mono_domain_get ();
- if (!image) {
- MonoArrayHandle arr = mono_array_new_handle (domain, mono_defaults.runtimetype_class, 0, error);
- return arr;
- } else {
- MonoArrayHandle exceptions = MONO_HANDLE_NEW (MonoArray, NULL);
- MonoArrayHandle res = mono_module_get_types (domain, image, exceptions, FALSE, error);
- return_val_if_nok (error, MONO_HANDLE_CAST(MonoArray, NULL_HANDLE));
- int n = mono_array_handle_length (exceptions);
- MonoExceptionHandle ex = MONO_HANDLE_NEW (MonoException, NULL);
- for (int i = 0; i < n; ++i) {
- MONO_HANDLE_ARRAY_GETREF(ex, exceptions, i);
- if (!MONO_HANDLE_IS_NULL (ex)) {
- mono_error_set_exception_handle (error, ex);
- return MONO_HANDLE_CAST(MonoArray, NULL_HANDLE);
- }
- }
- return res;
- }
- }
- static gboolean
- mono_memberref_is_method (MonoImage *image, guint32 token)
- {
- if (!image_is_dynamic (image)) {
- guint32 cols [MONO_MEMBERREF_SIZE];
- const char *sig;
- const MonoTableInfo *table = &image->tables [MONO_TABLE_MEMBERREF];
- int idx = mono_metadata_token_index (token) - 1;
- if (idx < 0 || table->rows <= idx) {
- return FALSE;
- }
- mono_metadata_decode_row (table, idx, cols, MONO_MEMBERREF_SIZE);
- sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
- mono_metadata_decode_blob_size (sig, &sig);
- return (*sig != 0x6);
- } else {
- ERROR_DECL (error);
- MonoClass *handle_class;
- if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, error)) {
- mono_error_cleanup (error); /* just probing, ignore error */
- return FALSE;
- }
- return mono_defaults.methodhandle_class == handle_class;
- }
- }
- static MonoGenericInst *
- get_generic_inst_from_array_handle (MonoArrayHandle type_args)
- {
- int type_argc = mono_array_handle_length (type_args);
- int size = MONO_SIZEOF_GENERIC_INST + type_argc * sizeof (MonoType *);
- MonoGenericInst *ginst = (MonoGenericInst *)g_alloca (size);
- memset (ginst, 0, MONO_SIZEOF_GENERIC_INST);
- ginst->type_argc = type_argc;
- for (int i = 0; i < type_argc; i++) {
- MONO_HANDLE_ARRAY_GETVAL (ginst->type_argv[i], type_args, MonoType*, i);
- }
- ginst->is_open = FALSE;
- for (int i = 0; i < type_argc; i++) {
- if (mono_class_is_open_constructed_type (ginst->type_argv[i])) {
- ginst->is_open = TRUE;
- break;
- }
- }
- return mono_metadata_get_canonical_generic_inst (ginst);
- }
- static void
- init_generic_context_from_args_handles (MonoGenericContext *context, MonoArrayHandle type_args, MonoArrayHandle method_args)
- {
- if (!MONO_HANDLE_IS_NULL (type_args)) {
- context->class_inst = get_generic_inst_from_array_handle (type_args);
- } else {
- context->class_inst = NULL;
- }
- if (!MONO_HANDLE_IS_NULL (method_args)) {
- context->method_inst = get_generic_inst_from_array_handle (method_args);
- } else {
- context->method_inst = NULL;
- }
- }
- static MonoType*
- module_resolve_type_token (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *resolve_error, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- error_init (error);
- MonoType *result = NULL;
- MonoClass *klass;
- int table = mono_metadata_token_table (token);
- int index = mono_metadata_token_index (token);
- MonoGenericContext context;
- *resolve_error = ResolveTokenError_Other;
- /* Validate token */
- if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
- (table != MONO_TABLE_TYPESPEC)) {
- *resolve_error = ResolveTokenError_BadTable;
- goto leave;
- }
- if (image_is_dynamic (image)) {
- if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
- ERROR_DECL (inner_error);
- klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, inner_error);
- mono_error_cleanup (inner_error);
- result = klass ? m_class_get_byval_arg (klass) : NULL;
- goto leave;
- }
- init_generic_context_from_args_handles (&context, type_args, method_args);
- ERROR_DECL (inner_error);
- klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, inner_error);
- mono_error_cleanup (inner_error);
- result = klass ? m_class_get_byval_arg (klass) : NULL;
- goto leave;
- }
- if ((index <= 0) || (index > image->tables [table].rows)) {
- *resolve_error = ResolveTokenError_OutOfRange;
- goto leave;
- }
- init_generic_context_from_args_handles (&context, type_args, method_args);
- klass = mono_class_get_checked (image, token, error);
- if (klass)
- klass = mono_class_inflate_generic_class_checked (klass, &context, error);
- goto_if_nok (error, leave);
- if (klass)
- result = m_class_get_byval_arg (klass);
- leave:
- HANDLE_FUNCTION_RETURN_VAL (result);
- }
- MonoType*
- ves_icall_System_Reflection_RuntimeModule_ResolveTypeToken (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *resolve_error, MonoError *error)
- {
- return module_resolve_type_token (image, token, type_args, method_args, resolve_error, error);
- }
- static MonoMethod*
- module_resolve_method_token (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *resolve_error, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- error_init (error);
- MonoMethod *method = NULL;
- int table = mono_metadata_token_table (token);
- int index = mono_metadata_token_index (token);
- MonoGenericContext context;
- *resolve_error = ResolveTokenError_Other;
- /* Validate token */
- if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
- (table != MONO_TABLE_MEMBERREF)) {
- *resolve_error = ResolveTokenError_BadTable;
- goto leave;
- }
- if (image_is_dynamic (image)) {
- if (table == MONO_TABLE_METHOD) {
- ERROR_DECL (inner_error);
- method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, inner_error);
- mono_error_cleanup (inner_error);
- goto leave;
- }
- if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
- *resolve_error = ResolveTokenError_BadTable;
- goto leave;
- }
- init_generic_context_from_args_handles (&context, type_args, method_args);
- ERROR_DECL (inner_error);
- method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, inner_error);
- mono_error_cleanup (inner_error);
- goto leave;
- }
- if ((index <= 0) || (index > image->tables [table].rows)) {
- *resolve_error = ResolveTokenError_OutOfRange;
- goto leave;
- }
- if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
- *resolve_error = ResolveTokenError_BadTable;
- goto leave;
- }
- init_generic_context_from_args_handles (&context, type_args, method_args);
- method = mono_get_method_checked (image, token, NULL, &context, error);
- leave:
- HANDLE_FUNCTION_RETURN_VAL (method);
- }
- MonoMethod*
- ves_icall_System_Reflection_RuntimeModule_ResolveMethodToken (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *resolve_error, MonoError *error)
- {
- return module_resolve_method_token (image, token, type_args, method_args, resolve_error, error);
- }
- MonoStringHandle
- ves_icall_System_Reflection_RuntimeModule_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error, MonoError *error)
- {
- int index = mono_metadata_token_index (token);
- *resolve_error = ResolveTokenError_Other;
- /* Validate token */
- if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
- *resolve_error = ResolveTokenError_BadTable;
- return NULL_HANDLE_STRING;
- }
- if (image_is_dynamic (image)) {
- ERROR_DECL (ignore_inner_error);
- // FIXME ignoring error
- // FIXME Push MONO_HANDLE_NEW to lower layers.
- MonoStringHandle result = MONO_HANDLE_NEW (MonoString, (MonoString*)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, ignore_inner_error));
- mono_error_cleanup (ignore_inner_error);
- return result;
- }
- if ((index <= 0) || (index >= image->heap_us.size)) {
- *resolve_error = ResolveTokenError_OutOfRange;
- return NULL_HANDLE_STRING;
- }
- /* FIXME: What to do if the index points into the middle of a string ? */
- return mono_ldstr_handle (mono_domain_get (), image, index, error);
- }
- static MonoClassField*
- module_resolve_field_token (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *resolve_error, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- MonoClass *klass;
- int table = mono_metadata_token_table (token);
- int index = mono_metadata_token_index (token);
- MonoGenericContext context;
- MonoClassField *field = NULL;
- error_init (error);
- *resolve_error = ResolveTokenError_Other;
- /* Validate token */
- if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
- *resolve_error = ResolveTokenError_BadTable;
- goto leave;
- }
- if (image_is_dynamic (image)) {
- if (table == MONO_TABLE_FIELD) {
- ERROR_DECL (inner_error);
- field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, inner_error);
- mono_error_cleanup (inner_error);
- goto leave;
- }
- if (mono_memberref_is_method (image, token)) {
- *resolve_error = ResolveTokenError_BadTable;
- goto leave;
- }
- init_generic_context_from_args_handles (&context, type_args, method_args);
- ERROR_DECL (inner_error);
- field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, inner_error);
- mono_error_cleanup (inner_error);
- goto leave;
- }
- if ((index <= 0) || (index > image->tables [table].rows)) {
- *resolve_error = ResolveTokenError_OutOfRange;
- goto leave;
- }
- if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
- *resolve_error = ResolveTokenError_BadTable;
- goto leave;
- }
- init_generic_context_from_args_handles (&context, type_args, method_args);
- field = mono_field_from_token_checked (image, token, &klass, &context, error);
-
- leave:
- HANDLE_FUNCTION_RETURN_VAL (field);
- }
- MonoClassField*
- ves_icall_System_Reflection_RuntimeModule_ResolveFieldToken (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *resolve_error, MonoError *error)
- {
- return module_resolve_field_token (image, token, type_args, method_args, resolve_error, error);
- }
- MonoObjectHandle
- ves_icall_System_Reflection_RuntimeModule_ResolveMemberToken (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *error, MonoError *merror)
- {
- int table = mono_metadata_token_table (token);
- *error = ResolveTokenError_Other;
- switch (table) {
- case MONO_TABLE_TYPEDEF:
- case MONO_TABLE_TYPEREF:
- case MONO_TABLE_TYPESPEC: {
- MonoType *t = module_resolve_type_token (image, token, type_args, method_args, error, merror);
- if (t) {
- return MONO_HANDLE_CAST (MonoObject, mono_type_get_object_handle (mono_domain_get (), t, merror));
- }
- else
- return NULL_HANDLE;
- }
- case MONO_TABLE_METHOD:
- case MONO_TABLE_METHODSPEC: {
- MonoMethod *m = module_resolve_method_token (image, token, type_args, method_args, error, merror);
- if (m) {
- return MONO_HANDLE_CAST (MonoObject, mono_method_get_object_handle (mono_domain_get (), m, m->klass, merror));
- } else
- return NULL_HANDLE;
- }
- case MONO_TABLE_FIELD: {
- MonoClassField *f = module_resolve_field_token (image, token, type_args, method_args, error, merror);
- if (f) {
- return MONO_HANDLE_CAST (MonoObject, mono_field_get_object_handle (mono_domain_get (), f->parent, f, merror));
- }
- else
- return NULL_HANDLE;
- }
- case MONO_TABLE_MEMBERREF:
- if (mono_memberref_is_method (image, token)) {
- MonoMethod *m = module_resolve_method_token (image, token, type_args, method_args, error, merror);
- if (m) {
- return MONO_HANDLE_CAST (MonoObject, mono_method_get_object_handle (mono_domain_get (), m, m->klass, merror));
- } else
- return NULL_HANDLE;
- }
- else {
- MonoClassField *f = module_resolve_field_token (image, token, type_args, method_args, error, merror);
- if (f) {
- return MONO_HANDLE_CAST (MonoObject, mono_field_get_object_handle (mono_domain_get (), f->parent, f, merror));
- }
- else
- return NULL_HANDLE;
- }
- break;
- default:
- *error = ResolveTokenError_BadTable;
- }
- return NULL_HANDLE;
- }
- MonoArrayHandle
- ves_icall_System_Reflection_RuntimeModule_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error, MonoError *error)
- {
- int table = mono_metadata_token_table (token);
- int idx = mono_metadata_token_index (token);
- MonoTableInfo *tables = image->tables;
- guint32 sig, len;
- const char *ptr;
- *resolve_error = ResolveTokenError_OutOfRange;
- /* FIXME: Support other tables ? */
- if (table != MONO_TABLE_STANDALONESIG)
- return NULL_HANDLE_ARRAY;
- if (image_is_dynamic (image))
- return NULL_HANDLE_ARRAY;
- if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
- return NULL_HANDLE_ARRAY;
- sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
- ptr = mono_metadata_blob_heap (image, sig);
- len = mono_metadata_decode_blob_size (ptr, &ptr);
- MonoArrayHandle res = mono_array_new_handle (mono_domain_get (), mono_defaults.byte_class, len, error);
- return_val_if_nok (error, NULL_HANDLE_ARRAY);
- // FIXME MONO_ENTER_NO_SAFEPOINTS instead of pin/gchandle.
- MonoGCHandle h;
- gpointer array_base = MONO_ARRAY_HANDLE_PIN (res, guint8, 0, &h);
- memcpy (array_base, ptr, len);
- mono_gchandle_free_internal (h);
- return res;
- }
- static void
- check_for_invalid_array_type (MonoClass *klass, MonoError *error)
- {
- char *name;
- error_init (error);
- if (m_class_get_byval_arg (klass)->type != MONO_TYPE_TYPEDBYREF)
- return;
- name = mono_type_get_full_name (klass);
- mono_error_set_type_load_name (error, name, g_strdup (""), "");
- }
- static void
- check_for_invalid_byref_or_pointer_type (MonoClass *klass, MonoError *error)
- {
- #ifdef ENABLE_NETCORE
- return;
- #else
- check_for_invalid_array_type (klass, error);
- #endif
- }
- MonoReflectionTypeHandle
- ves_icall_RuntimeType_make_array_type (MonoReflectionTypeHandle ref_type, int rank, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- check_for_invalid_array_type (klass, error);
- return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
- MonoClass *aklass;
- if (rank == 0) //single dimension array
- aklass = mono_class_create_array (klass, 1);
- else
- aklass = mono_class_create_bounded_array (klass, rank, TRUE);
- if (mono_class_has_failure (aklass)) {
- mono_error_set_for_class_failure (error, aklass);
- return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
- }
- MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
- return mono_type_get_object_handle (domain, m_class_get_byval_arg (aklass), error);
- }
- MonoReflectionTypeHandle
- ves_icall_RuntimeType_make_byref_type (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- mono_class_init_checked (klass, error);
- return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
- check_for_invalid_byref_or_pointer_type (klass, error);
- return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
- MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
- return mono_type_get_object_handle (domain, m_class_get_this_arg (klass), error);
- }
- MonoReflectionTypeHandle
- ves_icall_RuntimeType_MakePointerType (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- mono_class_init_checked (klass, error);
- return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
- check_for_invalid_byref_or_pointer_type (klass, error);
- return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
- MonoClass *pklass = mono_class_create_ptr (type);
- return mono_type_get_object_handle (domain, m_class_get_byval_arg (pklass), error);
- }
- MonoObjectHandle
- ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionTypeHandle ref_type, MonoObjectHandle target,
- MonoReflectionMethodHandle info, MonoBoolean throwOnBindFailure, MonoError *error)
- {
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- MonoClass *delegate_class = mono_class_from_mono_type_internal (type);
- MonoMethod *method = MONO_HANDLE_GETVAL (info, method);
- MonoMethodSignature *sig = mono_method_signature_internal (method);
- mono_class_init_checked (delegate_class, error);
- return_val_if_nok (error, NULL_HANDLE);
- if (!(m_class_get_parent (delegate_class) == mono_defaults.multicastdelegate_class)) {
- /* FIXME improve this exception message */
- mono_error_set_execution_engine (error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
- __func__,
- "delegate_class->parent == mono_defaults.multicastdelegate_class");
- return NULL_HANDLE;
- }
- if (mono_security_core_clr_enabled ()) {
- ERROR_DECL (security_error);
- if (!mono_security_core_clr_ensure_delegate_creation (method, security_error)) {
- if (throwOnBindFailure)
- mono_error_move (error, security_error);
- else
- mono_error_cleanup (security_error);
- return NULL_HANDLE;
- }
- }
- if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
- if (!method->is_inflated) {
- mono_error_set_argument (error, "method", " Cannot bind to the target method because its signature differs from that of the delegate type");
- return NULL_HANDLE;
- }
- }
- MonoObjectHandle delegate = mono_object_new_handle (MONO_HANDLE_DOMAIN (ref_type), delegate_class, error);
- return_val_if_nok (error, NULL_HANDLE);
- if (!method_is_dynamic (method) && (!MONO_HANDLE_IS_NULL (target) && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_handle_class (target))) {
- method = mono_object_handle_get_virtual_method (target, method, error);
- return_val_if_nok (error, NULL_HANDLE);
- }
- mono_delegate_ctor (delegate, target, NULL, method, error);
- return_val_if_nok (error, NULL_HANDLE);
- return delegate;
- }
- MonoMulticastDelegateHandle
- ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegateHandle delegate, MonoError *error)
- {
- MonoClass *klass = mono_handle_class (delegate);
- g_assert (mono_class_has_parent (klass, mono_defaults.multicastdelegate_class));
- MonoMulticastDelegateHandle ret = MONO_HANDLE_CAST (MonoMulticastDelegate, mono_object_new_handle (MONO_HANDLE_DOMAIN (delegate), klass, error));
- return_val_if_nok (error, MONO_HANDLE_CAST (MonoMulticastDelegate, NULL_HANDLE));
- MONO_HANDLE_SETVAL (MONO_HANDLE_CAST (MonoDelegate, ret), invoke_impl, gpointer, mono_runtime_create_delegate_trampoline (klass));
- return ret;
- }
- MonoReflectionMethodHandle
- ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegateHandle delegate, MonoError *error)
- {
- MonoObjectHandle delegate_target = MONO_HANDLE_NEW_GET (MonoObject, delegate, target);
- MonoMethod *m = mono_object_handle_get_virtual_method (delegate_target, MONO_HANDLE_GETVAL (delegate, method), error);
- return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE));
- return mono_method_get_object_handle (mono_domain_get (), m, m->klass, error);
- }
- /* System.Buffer */
- static gint32
- mono_array_get_byte_length (MonoArrayHandle array)
- {
- int length;
- MonoClass * const klass = mono_handle_class (array);
- // This resembles mono_array_get_length, but adds the loop.
- if (mono_handle_array_has_bounds (array)) {
- length = 1;
- const int klass_rank = m_class_get_rank (klass);
- for (int i = 0; i < klass_rank; ++ i)
- length *= MONO_HANDLE_GETVAL (array, bounds [i].length);
- } else {
- length = mono_array_handle_length (array);
- }
- switch (m_class_get_byval_arg (m_class_get_element_class (klass))->type) {
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- case MONO_TYPE_BOOLEAN:
- return length;
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- case MONO_TYPE_CHAR:
- return length << 1;
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_R4:
- return length << 2;
- case MONO_TYPE_I:
- case MONO_TYPE_U:
- return length * sizeof (gpointer);
- case MONO_TYPE_I8:
- case MONO_TYPE_U8:
- case MONO_TYPE_R8:
- return length << 3;
- default:
- return -1;
- }
- }
- #ifndef ENABLE_NETCORE
- gint32
- ves_icall_System_Buffer_ByteLengthInternal (MonoArrayHandle array, MonoError* error)
- {
- return mono_array_get_byte_length (array);
- }
- void
- ves_icall_System_Buffer_MemcpyInternal (gpointer dest, gconstpointer src, gint32 count)
- {
- memcpy (dest, src, count);
- }
- MonoBoolean
- ves_icall_System_Buffer_BlockCopyInternal (MonoArrayHandle src, gint32 src_offset, MonoArrayHandle dest, gint32 dest_offset, gint32 count, MonoError* error)
- {
- if (count < 0) {
- mono_error_set_argument (error, "count", "is negative");
- return FALSE;
- }
- /* This is called directly from the class libraries without going through the managed wrapper */
- MONO_CHECK_ARG_NULL_HANDLE (src, FALSE);
- MONO_CHECK_ARG_NULL_HANDLE (dest, FALSE);
- /* watch out for integer overflow */
- if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
- return FALSE;
- MONO_ENTER_NO_SAFEPOINTS;
- guint8 const * const src_buf = (guint8*)MONO_HANDLE_RAW (src)->vector + src_offset;
- guint8* const dest_buf = (guint8*)MONO_HANDLE_RAW (dest)->vector + dest_offset;
- #if !HOST_WIN32
- // Windows memcpy is memmove and checks for overlap anyway, so skip
- // the check here that would not help.
- if (MONO_HANDLE_RAW (src) != MONO_HANDLE_RAW (dest))
- memcpy (dest_buf, src_buf, count);
- else
- #endif
- memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
- MONO_EXIT_NO_SAFEPOINTS;
- return TRUE;
- }
- #endif
- #ifndef DISABLE_REMOTING
- MonoObjectHandle
- ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObjectHandle this_obj, MonoStringHandle class_name, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (this_obj);
- MonoRealProxyHandle rp = MONO_HANDLE_CAST (MonoRealProxy, this_obj);
- MonoObjectHandle res = mono_object_new_handle (domain, mono_defaults.transparent_proxy_class, error);
- return_val_if_nok (error, NULL_HANDLE);
- MonoTransparentProxyHandle tp = MONO_HANDLE_CAST (MonoTransparentProxy, res);
-
- MONO_HANDLE_SET (tp, rp, rp);
- MonoReflectionTypeHandle reftype = MONO_HANDLE_NEW (MonoReflectionType, NULL);
- MONO_HANDLE_GET (reftype, rp, class_to_proxy);
- MonoType *type = MONO_HANDLE_GETVAL (reftype, type);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
- mono_class_setup_vtable (klass);
- if (mono_class_has_failure (klass)) {
- mono_error_set_for_class_failure (error, klass);
- return NULL_HANDLE;
- }
- MonoObjectHandle remoting_obj = mono_object_handle_isinst (this_obj, mono_defaults.iremotingtypeinfo_class, error);
- return_val_if_nok (error, NULL_HANDLE);
- MONO_HANDLE_SETVAL (tp, custom_type_info, MonoBoolean, !MONO_HANDLE_IS_NULL (remoting_obj));
- MonoRemoteClass *remote_class = (MonoRemoteClass*)mono_remote_class (domain, class_name, klass, error);
- return_val_if_nok (error, NULL_HANDLE);
- MONO_HANDLE_SETVAL (tp, remote_class, MonoRemoteClass*, remote_class);
- MONO_HANDLE_SETVAL (res, vtable, MonoVTable*, (MonoVTable*)mono_remote_class_vtable (domain, remote_class, rp, error));
- return_val_if_nok (error, NULL_HANDLE);
- return res;
- }
- MonoReflectionTypeHandle
- ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxyHandle tp, MonoError *error)
- {
- MonoRemoteClass *remote_class;
- g_assert (mono_handle_class (tp) == mono_defaults.transparent_proxy_class);
- remote_class = MONO_HANDLE_RAW (tp)->remote_class;
- g_assert (remote_class != NULL && remote_class->proxy_class != NULL);
- return mono_type_get_object_handle (mono_handle_domain (tp), m_class_get_byval_arg (remote_class->proxy_class), error);
- }
- #endif
- /* System.Environment */
- #ifndef ENABLE_NETCORE
- MonoStringHandle
- ves_icall_System_Environment_get_UserName (MonoError *error)
- {
- /* using glib is more portable */
- const gchar *user_name = g_get_user_name ();
- if (user_name != NULL)
- return mono_string_new_handle (mono_domain_get (), user_name, error);
- else
- return NULL_HANDLE_STRING;
- }
- #ifndef HOST_WIN32
- static MonoStringHandle
- mono_icall_get_machine_name (MonoError *error)
- {
- #if !defined(DISABLE_SOCKETS)
- MonoStringHandle result;
- char *buf;
- int n;
- #if defined _SC_HOST_NAME_MAX
- n = sysconf (_SC_HOST_NAME_MAX);
- if (n == -1)
- #endif
- n = 512;
- buf = (char*)g_malloc (n + 1);
- #if defined(HAVE_GETHOSTNAME)
- if (gethostname (buf, n) == 0){
- buf [n] = 0;
- int i;
- // try truncating the string at the first dot
- for (i = 0; i < n; i++) {
- if (buf [i] == '.') {
- buf [i] = 0;
- break;
- }
- }
- result = mono_string_new_handle (mono_domain_get (), buf, error);
- } else
- #endif
- result = MONO_HANDLE_CAST (MonoString, NULL_HANDLE);
- g_free (buf);
-
- return result;
- #else
- return mono_string_new_handle (mono_domain_get (), "mono", error);
- #endif
- }
- #endif /* !HOST_WIN32 */
- MonoStringHandle
- ves_icall_System_Environment_get_MachineName (MonoError *error)
- {
- return mono_icall_get_machine_name (error);
- }
- #ifndef HOST_WIN32
- static int
- mono_icall_get_platform (void)
- {
- #if defined(__MACH__)
- /* OSX */
- //
- // Notice that the value is hidden from user code, and only exposed
- // to mscorlib. This is due to Mono's Unix/MacOS code predating the
- // define and making assumptions based on Unix/128/4 values before there
- // was a MacOS define. Lots of code would assume that not-Unix meant
- // Windows, but in this case, it would be OSX.
- //
- return 6;
- #else
- /* Unix */
- return 4;
- #endif
- }
- #endif /* !HOST_WIN32 */
- int
- ves_icall_System_Environment_get_Platform (void)
- {
- return mono_icall_get_platform ();
- }
- #endif /* !ENABLE_NETCORE */
- #ifndef HOST_WIN32
- static MonoStringHandle
- mono_icall_get_new_line (MonoError *error)
- {
- return mono_string_new_handle (mono_domain_get (), "\n", error);
- }
- #endif /* !HOST_WIN32 */
- #ifndef ENABLE_NETCORE
- MonoStringHandle
- ves_icall_System_Environment_get_NewLine (MonoError *error)
- {
- return mono_icall_get_new_line (error);
- }
- #endif
- #ifndef HOST_WIN32
- static inline MonoBoolean
- mono_icall_is_64bit_os (void)
- {
- #if SIZEOF_VOID_P == 8
- return TRUE;
- #else
- #if defined(HAVE_SYS_UTSNAME_H)
- struct utsname name;
- if (uname (&name) >= 0) {
- return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0 || strncmp (name.machine, "riscv64", 7) == 0;
- }
- #endif
- return FALSE;
- #endif
- }
- #endif /* !HOST_WIN32 */
- MonoBoolean
- ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
- {
- return mono_icall_is_64bit_os ();
- }
- MonoStringHandle
- ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
- {
- gchar *value;
- if (utf8_name == NULL)
- return NULL_HANDLE_STRING;
- value = g_getenv (utf8_name);
- if (value == 0)
- return NULL_HANDLE_STRING;
-
- MonoStringHandle res = mono_string_new_handle (mono_domain_get (), value, error);
- g_free (value);
- return res;
- }
- /*
- * There is no standard way to get at environ.
- */
- #ifndef _MSC_VER
- #ifndef __MINGW32_VERSION
- #if defined(__APPLE__)
- #if defined (TARGET_OSX)
- /* Apple defines this in crt_externs.h but doesn't provide that header for
- * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
- * in fact exist on all implementations (so far)
- */
- G_BEGIN_DECLS
- gchar ***_NSGetEnviron(void);
- G_END_DECLS
- #define environ (*_NSGetEnviron())
- #else
- static char *mono_environ[1] = { NULL };
- #define environ mono_environ
- #endif /* defined (TARGET_OSX) */
- #else
- G_BEGIN_DECLS
- extern
- char **environ;
- G_END_DECLS
- #endif
- #endif
- #endif
- MonoArrayHandle
- ves_icall_System_Environment_GetCommandLineArgs (MonoError *error)
- {
- MonoArrayHandle result = mono_runtime_get_main_args_handle (error);
- return result;
- }
- #ifndef HOST_WIN32
- static MonoArrayHandle
- mono_icall_get_environment_variable_names (MonoError *error)
- {
- MonoArrayHandle names;
- MonoDomain *domain;
- MonoStringHandle str;
- gchar **e, **parts;
- int n;
- n = 0;
- for (e = environ; *e != 0; ++ e)
- ++ n;
- domain = mono_domain_get ();
- names = mono_array_new_handle (domain, mono_defaults.string_class, n, error);
- return_val_if_nok (error, NULL_HANDLE_ARRAY);
- str = MONO_HANDLE_NEW (MonoString, NULL);
- n = 0;
- for (e = environ; *e != 0; ++ e) {
- parts = g_strsplit (*e, "=", 2);
- if (*parts != 0) {
- MonoString *s = mono_string_new_checked (domain, *parts, error);
- MONO_HANDLE_ASSIGN_RAW (str, s);
- if (!is_ok (error)) {
- g_strfreev (parts);
- return NULL_HANDLE_ARRAY;
- }
- mono_array_handle_setref (names, n, str);
- }
- g_strfreev (parts);
- ++ n;
- }
- return names;
- }
- #endif /* !HOST_WIN32 */
- MonoArrayHandle
- ves_icall_System_Environment_GetEnvironmentVariableNames (MonoError *error)
- {
- return mono_icall_get_environment_variable_names (error);
- }
- #ifndef ENABLE_NETCORE
- void
- ves_icall_System_Environment_InternalSetEnvironmentVariable (const gunichar2 *name, gint32 name_length,
- const gunichar2 *value, gint32 value_length, MonoError *error)
- {
- #ifdef HOST_WIN32
- if (!value || !value_length || !value [0])
- value = NULL;
- SetEnvironmentVariableW (name, value);
- #else
- char *utf8_name = NULL;
- char *utf8_value = NULL;
- utf8_name = mono_utf16_to_utf8 (name, name_length, error); // FIXME: this should be ascii
- goto_if_nok (error, exit);
- if (!value || !value_length || !value [0]) {
- g_unsetenv (utf8_name);
- goto exit;
- }
- utf8_value = mono_utf16_to_utf8 (value, value_length, error);
- goto_if_nok (error, exit);
- g_setenv (utf8_name, utf8_value, TRUE);
- exit:
- g_free (utf8_name);
- g_free (utf8_value);
- #endif
- }
- #endif
- void
- ves_icall_System_Environment_Exit (int result)
- {
- mono_environment_exitcode_set (result);
- if (!mono_runtime_try_shutdown ())
- mono_thread_exit ();
- #ifndef ENABLE_NETCORE
- /* Suspend all managed threads since the runtime is going away */
- mono_thread_suspend_all_other_threads ();
- #endif
- mono_runtime_quit_internal ();
- /* we may need to do some cleanup here... */
- exit (result);
- }
- void
- ves_icall_System_Environment_FailFast (MonoStringHandle message, MonoExceptionHandle exception, MonoStringHandle errorSource, MonoError *error)
- {
- if (MONO_HANDLE_IS_NULL (message)) {
- g_warning ("CLR: Managed code called FailFast without specifying a reason.");
- } else {
- char *msg = mono_string_handle_to_utf8 (message, error);
- g_warning ("CLR: Managed code called FailFast, saying \"%s\"", msg);
- #ifndef DISABLE_CRASH_REPORTING
- char *old_msg = mono_crash_save_failfast_msg (msg);
- g_free (old_msg);
- #else
- g_free (msg);
- #endif
- }
- if (!MONO_HANDLE_IS_NULL (exception)) {
- mono_print_unhandled_exception_internal ((MonoObject *) MONO_HANDLE_RAW (exception));
- }
- // NOTE: While this does trigger WER on Windows it doesn't quite provide all the
- // information in the error dump that CoreCLR would. On Windows 7+ we should call
- // RaiseFailFastException directly instead of relying on the C runtime doing it
- // for us and pass it as much information as possible. On Windows 8+ we can also
- // use the __fastfail intrinsic.
- abort ();
- }
- #ifndef ENABLE_NETCORE
- MonoStringHandle
- ves_icall_System_Environment_GetGacPath (MonoError *error)
- {
- return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
- }
- #endif
- #ifndef HOST_WIN32
- static inline MonoStringHandle
- mono_icall_get_windows_folder_path (int folder, MonoError *error)
- {
- error_init (error);
- g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
- return mono_string_new_handle (mono_domain_get (), "", error);
- }
- #endif /* !HOST_WIN32 */
- #ifndef ENABLE_NETCORE
- MonoStringHandle
- ves_icall_System_Environment_GetWindowsFolderPath (int folder, MonoError *error)
- {
- return mono_icall_get_windows_folder_path (folder, error);
- }
- #endif
- static MonoArrayHandle
- mono_icall_get_logical_drives (MonoError *error)
- {
- gunichar2 buf [256], *ptr, *dname;
- gunichar2 *u16;
- guint initial_size = 127, size = 128;
- gint ndrives;
- MonoArrayHandle result = NULL_HANDLE_ARRAY;
- MonoStringHandle drivestr;
- MonoDomain *domain = mono_domain_get ();
- gint len;
- buf [0] = '\0';
- ptr = buf;
- while (size > initial_size) {
- size = (guint) mono_w32file_get_logical_drive (initial_size, ptr, error);
- if (!is_ok (error))
- goto leave;
- if (size > initial_size) {
- if (ptr != buf)
- g_free (ptr);
- ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
- initial_size = size;
- size++;
- }
- }
- /* Count strings */
- dname = ptr;
- ndrives = 0;
- do {
- while (*dname++);
- ndrives++;
- } while (*dname);
- dname = ptr;
- result = mono_array_new_handle (domain, mono_defaults.string_class, ndrives, error);
- goto_if_nok (error, leave);
- drivestr = MONO_HANDLE_NEW (MonoString, NULL);
- ndrives = 0;
- do {
- len = 0;
- u16 = dname;
- while (*u16) {
- u16++; len ++;
- }
- MonoString *s = mono_string_new_utf16_checked (domain, dname, len, error);
- goto_if_nok (error, leave);
- MONO_HANDLE_ASSIGN_RAW (drivestr, s);
- mono_array_handle_setref (result, ndrives, drivestr);
- ndrives ++;
- while (*dname++);
- } while (*dname);
- leave:
- if (ptr != buf)
- g_free (ptr);
- return result;
- }
- #ifndef ENABLE_NETCORE
- MonoArrayHandle
- ves_icall_System_Environment_GetLogicalDrivesInternal (MonoError *error)
- {
- return mono_icall_get_logical_drives (error);
- }
- guint32
- ves_icall_System_IO_DriveInfo_GetDriveType (const gunichar2 *root_path_name, gint32 root_path_name_length, MonoError *error)
- {
- return mono_w32file_get_drive_type (root_path_name, root_path_name_length, error);
- }
- MonoStringHandle
- ves_icall_System_IO_DriveInfo_GetDriveFormat (const gunichar2 *path, gint32 path_length, MonoError *error)
- {
- gunichar2 volume_name [MAX_PATH + 1];
-
- if (mono_w32file_get_file_system_type (path, volume_name, MAX_PATH + 1) == FALSE)
- return NULL_HANDLE_STRING;
- return mono_string_new_utf16_handle (mono_domain_get (), volume_name, g_utf16_len (volume_name), error);
- }
- MonoStringHandle
- ves_icall_System_Environment_InternalGetHome (MonoError *error)
- {
- const gchar *home_dir = g_get_home_dir ();
- if (home_dir != NULL)
- return mono_string_new_handle (mono_domain_get (), home_dir, error);
- else
- return NULL_HANDLE_STRING;
- }
- static const char * const encodings [] = {
- (char *) 1,
- "ascii", "us_ascii", "us", "ansi_x3.4_1968",
- "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
- "iso_ir_6", "iso646_us", "iso_646.irv:1991",
- (char *) 2,
- "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
- "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
- "x_unicode_2_0_utf_7",
- (char *) 3,
- "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
- "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
- (char *) 4,
- "utf_16", "UTF_16LE", "ucs_2", "unicode",
- "iso_10646_ucs2",
- (char *) 5,
- "unicodefffe", "utf_16be",
- (char *) 6,
- "iso_8859_1",
- (char *) 0
- };
- /*
- * Returns the internal codepage, if the value of "int_code_page" is
- * 1 at entry, and we can not compute a suitable code page number,
- * returns the code page as a string
- */
- MonoStringHandle
- ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page, MonoError *error)
- {
- error_init (error);
- const char *cset;
- const char *p;
- char *c;
- char *codepage = NULL;
- int code;
- int want_name = *int_code_page;
- int i;
-
- *int_code_page = -1;
- g_get_charset (&cset);
- c = codepage = g_strdup (cset);
- for (c = codepage; *c; c++){
- if (isascii (*c) && isalpha (*c))
- *c = tolower (*c);
- if (*c == '-')
- *c = '_';
- }
- /* g_print ("charset: %s\n", cset); */
-
- /* handle some common aliases */
- p = encodings [0];
- code = 0;
- for (i = 0; p != 0; ){
- if ((gsize) p < 7){
- code = (gssize) p;
- p = encodings [++i];
- continue;
- }
- if (strcmp (p, codepage) == 0){
- *int_code_page = code;
- break;
- }
- p = encodings [++i];
- }
-
- if (strstr (codepage, "utf_8") != NULL)
- *int_code_page |= 0x10000000;
- g_free (codepage);
-
- if (want_name && *int_code_page == -1)
- return mono_string_new_handle (mono_domain_get (), cset, error);
- return NULL_HANDLE_STRING;
- }
- #endif
- MonoBoolean
- ves_icall_System_Environment_get_HasShutdownStarted (void)
- {
- return mono_runtime_is_shutting_down () || mono_domain_is_unloading (mono_domain_get ());
- }
- #ifndef HOST_WIN32
- #ifndef ENABLE_NETCORE
- void
- ves_icall_System_Environment_BroadcastSettingChange (MonoError *error)
- {
- }
- #endif
- #endif
- gint32
- ves_icall_System_Environment_get_TickCount (void)
- {
- /* this will overflow after ~24 days */
- return (gint32) (mono_msec_boottime () & 0xffffffff);
- }
- #if ENABLE_NETCORE
- gint64
- ves_icall_System_Environment_get_TickCount64 (void)
- {
- return mono_msec_boottime ();
- }
- #endif
- #ifndef ENABLE_NETCORE
- gint32
- ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (MonoError *error)
- {
- return 9;
- }
- #endif
- #ifndef DISABLE_REMOTING
- MonoBoolean
- ves_icall_IsTransparentProxy (MonoObjectHandle proxy, MonoError *error)
- {
- if (MONO_HANDLE_IS_NULL (proxy))
- return 0;
- if (mono_class_is_transparent_proxy (mono_handle_class (proxy)))
- return 1;
- return 0;
- }
- MonoReflectionMethodHandle
- ves_icall_Remoting_RemotingServices_GetVirtualMethod (
- MonoReflectionTypeHandle rtype, MonoReflectionMethodHandle rmethod, MonoError *error)
- {
- MonoReflectionMethodHandle ret = MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
- if (MONO_HANDLE_IS_NULL (rtype)) {
- mono_error_set_argument_null (error, "type", "");
- return ret;
- }
- if (MONO_HANDLE_IS_NULL (rmethod)) {
- mono_error_set_argument_null (error, "method", "");
- return ret;
- }
- MonoMethod *method = MONO_HANDLE_GETVAL (rmethod, method);
- MonoType *type = MONO_HANDLE_GETVAL (rtype, type);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- mono_class_init_checked (klass, error);
- return_val_if_nok (error, ret);
- if (MONO_CLASS_IS_INTERFACE_INTERNAL (klass))
- return ret;
- if (method->flags & METHOD_ATTRIBUTE_STATIC)
- return ret;
- if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
- if (klass == method->klass || mono_class_is_subclass_of_internal (klass, method->klass, FALSE))
- ret = rmethod;
- return ret;
- }
- mono_class_setup_vtable (klass);
- MonoMethod **vtable = m_class_get_vtable (klass);
- MonoMethod *res = NULL;
- if (mono_class_is_interface (method->klass)) {
- gboolean variance_used = FALSE;
- /*MS fails with variant interfaces but it's the right thing to do anyway.*/
- int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
- if (offs >= 0)
- res = vtable [offs + method->slot];
- } else {
- if (!(klass == method->klass || mono_class_is_subclass_of_internal (klass, method->klass, FALSE)))
- return ret;
- if (method->slot != -1)
- res = vtable [method->slot];
- }
- if (!res)
- return ret;
- ret = mono_method_get_object_handle (mono_domain_get (), res, NULL, error);
- return ret;
- }
- void
- ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionTypeHandle type, MonoBoolean enable, MonoError *error)
- {
- MonoClass *klass = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (type, type));
- MonoVTable *vtable = mono_class_vtable_checked (mono_domain_get (), klass, error);
- return_if_nok (error);
- mono_vtable_set_is_remote (vtable, enable);
- }
- #else /* DISABLE_REMOTING */
- ICALL_EXPORT MonoBoolean
- ves_icall_IsTransparentProxy (MonoObject *proxy)
- {
- return 0;
- }
- #ifndef ENABLE_NETCORE
- void
- ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionTypeHandle type, MonoBoolean enable, MonoError *error)
- {
- g_assert_not_reached ();
- }
- #endif
- #endif
- #ifndef ENABLE_NETCORE
- MonoObjectHandle
- ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionTypeHandle type, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (type);
- MonoClass *klass = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (type, type));
- mono_class_init_checked (klass, error);
- return_val_if_nok (error, NULL_HANDLE);
- if (MONO_CLASS_IS_INTERFACE_INTERNAL (klass) || mono_class_is_abstract (klass)) {
- mono_error_set_argument (error, "type", "Type cannot be instantiated");
- return NULL_HANDLE;
- }
- if (m_class_get_rank (klass) >= 1) {
- g_assert (m_class_get_rank (klass) == 1);
- return MONO_HANDLE_CAST (MonoObject, mono_array_new_handle (domain, m_class_get_element_class (klass), 0, error));
- } else {
- MonoVTable *vtable = mono_class_vtable_checked (domain, klass, error);
- return_val_if_nok (error, NULL_HANDLE);
- /* Bypass remoting object creation check */
- return MONO_HANDLE_NEW (MonoObject, mono_object_new_alloc_specific_checked (vtable, error));
- }
- }
- MonoStringHandle
- ves_icall_System_IO_get_temp_path (MonoError *error)
- {
- return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
- }
- #if defined(ENABLE_MONODROID) || defined(ENABLE_MONOTOUCH) || defined(TARGET_WASM)
- // FIXME? Names should start "mono"?
- G_EXTERN_C gpointer CreateZStream (gint32 compress, MonoBoolean gzip, gpointer feeder, gpointer data);
- G_EXTERN_C gint32 CloseZStream (gpointer stream);
- G_EXTERN_C gint32 Flush (gpointer stream);
- G_EXTERN_C gint32 ReadZStream (gpointer stream, gpointer buffer, gint32 length);
- G_EXTERN_C gint32 WriteZStream (gpointer stream, gpointer buffer, gint32 length);
- gpointer
- ves_icall_System_IO_Compression_DeflateStreamNative_CreateZStream (gint32 compress, MonoBoolean gzip, gpointer feeder, gpointer data)
- {
- #ifdef MONO_CROSS_COMPILE
- return NULL;
- #else
- return CreateZStream (compress, gzip, feeder, data);
- #endif
- }
- gint32
- ves_icall_System_IO_Compression_DeflateStreamNative_CloseZStream (gpointer stream)
- {
- #ifdef MONO_CROSS_COMPILE
- return 0;
- #else
- return CloseZStream (stream);
- #endif
- }
- gint32
- ves_icall_System_IO_Compression_DeflateStreamNative_Flush (gpointer stream)
- {
- #ifdef MONO_CROSS_COMPILE
- return 0;
- #else
- return Flush (stream);
- #endif
- }
- gint32
- ves_icall_System_IO_Compression_DeflateStreamNative_ReadZStream (gpointer stream, gpointer buffer, gint32 length)
- {
- #ifdef MONO_CROSS_COMPILE
- return 0;
- #else
- return ReadZStream (stream, buffer, length);
- #endif
- }
- gint32
- ves_icall_System_IO_Compression_DeflateStreamNative_WriteZStream (gpointer stream, gpointer buffer, gint32 length)
- {
- #ifdef MONO_CROSS_COMPILE
- return 0;
- #else
- return WriteZStream (stream, buffer, length);
- #endif
- }
- #endif
- #if defined(TARGET_WASM)
- G_EXTERN_C void mono_timezone_get_local_name (MonoString **result);
- void
- ves_icall_System_TimeZoneInfo_mono_timezone_get_local_name (MonoString **result)
- {
- // MONO_CROSS_COMPILE returns undefined symbol "_mono_timezone_get_local_name"
- // The icall offsets will be generated and linked at build time
- // This is defined outside the runtime within the webassembly sdk
- #ifndef MONO_CROSS_COMPILE
- return mono_timezone_get_local_name (result);
- #endif
- }
- #endif
- #endif /* ENABLE_NETCORE */
- #ifndef PLATFORM_NO_DRIVEINFO
- MonoBoolean
- ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (const gunichar2 *path_name, gint32 path_name_length, guint64 *free_bytes_avail,
- guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
- gint32 *error)
- {
- g_assert (error);
- g_assert (free_bytes_avail);
- g_assert (total_number_of_bytes);
- g_assert (total_number_of_free_bytes);
- // FIXME check for embedded nuls here or managed
- *error = ERROR_SUCCESS;
- *free_bytes_avail = (guint64)-1;
- *total_number_of_bytes = (guint64)-1;
- *total_number_of_free_bytes = (guint64)-1;
- gboolean result = mono_w32file_get_disk_free_space (path_name, free_bytes_avail, total_number_of_bytes, total_number_of_free_bytes);
- if (!result)
- *error = mono_w32error_get_last ();
- return result;
- }
- #endif /* PLATFORM_NO_DRIVEINFO */
- gpointer
- ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method, MonoError *error)
- {
- return mono_compile_method_checked (method, error);
- }
- #ifndef ENABLE_NETCORE
- MonoStringHandle
- ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (MonoError *error)
- {
- gchar *path;
- const char *mono_cfg_dir = mono_get_config_dir ();
- if (!mono_cfg_dir)
- return mono_string_new_handle (mono_domain_get (), "", error);
- path = g_build_path (G_DIR_SEPARATOR_S, mono_cfg_dir, "mono", mono_get_runtime_info ()->framework_version, "machine.config", (const char*)NULL);
- mono_icall_make_platform_path (path);
- MonoStringHandle mcpath = mono_string_new_handle (mono_domain_get (), path, error);
- g_free (path);
- mono_error_assert_ok (error);
- return mcpath;
- }
- MonoStringHandle
- ves_icall_System_Configuration_InternalConfigurationHost_get_bundled_app_config (MonoError *error)
- {
- const gchar *app_config;
- MonoDomain *domain;
- gchar *config_file_name, *config_file_path;
- gsize len, config_file_path_length, config_ext_length;
- gchar *module;
- domain = mono_domain_get ();
- MonoStringHandle file = MONO_HANDLE_NEW (MonoString, domain->setup->configuration_file);
- if (MONO_HANDLE_IS_NULL (file) || MONO_HANDLE_GETVAL (file, length) == 0)
- return MONO_HANDLE_CAST (MonoString, mono_new_null ());
- // Retrieve config file and remove the extension
- config_file_name = mono_string_handle_to_utf8 (file, error);
- return_val_if_nok (error, MONO_HANDLE_CAST (MonoString, NULL_HANDLE));
- config_file_path = mono_portability_find_file (config_file_name, TRUE);
- if (!config_file_path)
- config_file_path = config_file_name;
- config_file_path_length = strlen (config_file_path);
- config_ext_length = strlen (".config");
- if (config_file_path_length <= config_ext_length) {
- if (config_file_name != config_file_path)
- g_free (config_file_name);
- return MONO_HANDLE_CAST (MonoString, NULL_HANDLE);
- }
- len = config_file_path_length - config_ext_length;
- module = (gchar *)g_malloc0 (len + 1);
- memcpy (module, config_file_path, len);
- // Get the config file from the module name
- app_config = mono_config_string_for_assembly_file (module);
- // Clean-up
- g_free (module);
- if (config_file_name != config_file_path)
- g_free (config_file_name);
- g_free (config_file_path);
- if (!app_config)
- return MONO_HANDLE_CAST (MonoString, NULL_HANDLE);
- return mono_string_new_handle (mono_domain_get (), app_config, error);
- }
- static MonoStringHandle
- get_bundled_machine_config (MonoError *error)
- {
- const gchar *machine_config;
- machine_config = mono_get_machine_config ();
- if (!machine_config)
- return NULL_HANDLE_STRING;
- return mono_string_new_handle (mono_domain_get (), machine_config, error);
- }
- MonoStringHandle
- ves_icall_System_Environment_get_bundled_machine_config (MonoError *error)
- {
- return get_bundled_machine_config (error);
- }
- MonoStringHandle
- ves_icall_System_Configuration_DefaultConfig_get_bundled_machine_config (MonoError *error)
- {
- return get_bundled_machine_config (error);
- }
- MonoStringHandle
- ves_icall_System_Configuration_InternalConfigurationHost_get_bundled_machine_config (MonoError *error)
- {
- return get_bundled_machine_config (error);
- }
- MonoStringHandle
- ves_icall_System_Web_Util_ICalls_get_machine_install_dir (MonoError *error)
- {
- const char *mono_cfg_dir = mono_get_config_dir ();
- if (!mono_cfg_dir)
- return mono_string_new_handle (mono_domain_get (), "", error);
- char *path = g_path_get_dirname (mono_cfg_dir);
- mono_icall_make_platform_path (path);
- MonoStringHandle ipath = mono_string_new_handle (mono_domain_get (), path, error);
- g_free (path);
- return ipath;
- }
- MonoBoolean
- ves_icall_get_resources_ptr (MonoReflectionAssemblyHandle assembly, gpointer *result, gint32 *size, MonoError *error)
- {
- MonoPEResourceDataEntry *entry;
- MonoImage *image;
- if (MONO_HANDLE_IS_NULL (assembly) || !result || !size)
- return FALSE;
- *result = NULL;
- *size = 0;
- MonoAssembly *assm = MONO_HANDLE_GETVAL (assembly, assembly);
- image = assm->image;
- entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
- if (!entry)
- return FALSE;
- *result = mono_image_rva_map (image, entry->rde_data_offset);
- if (!(*result)) {
- g_free (entry);
- return FALSE;
- }
- *size = entry->rde_size;
- g_free (entry);
- return TRUE;
- }
- #endif /* ENABLE_NETCORE */
- MonoBoolean
- ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
- {
- return mono_is_debugger_attached ();
- }
- MonoBoolean
- ves_icall_System_Diagnostics_Debugger_IsLogging (void)
- {
- return mono_get_runtime_callbacks ()->debug_log_is_enabled
- && mono_get_runtime_callbacks ()->debug_log_is_enabled ();
- }
- void
- ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *volatile* category, MonoString *volatile* message)
- {
- if (mono_get_runtime_callbacks ()->debug_log)
- mono_get_runtime_callbacks ()->debug_log (level, *category, *message);
- }
- #ifndef HOST_WIN32
- static inline void
- mono_icall_write_windows_debug_string (const gunichar2 *message)
- {
- g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
- }
- #endif /* !HOST_WIN32 */
- #ifndef ENABLE_NETCORE
- void
- ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (const gunichar2 *message, MonoError *error)
- {
- mono_icall_write_windows_debug_string (message);
- }
- #endif
- /* Only used for value types */
- MonoObjectHandle
- ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionTypeHandle ref_type, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
- MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- (void)klass;
- mono_class_init_checked (klass, error);
- return_val_if_nok (error, NULL_HANDLE);
- if (mono_class_is_nullable (klass))
- /* No arguments -> null */
- return NULL_HANDLE;
- return mono_object_new_handle (domain, klass, error);
- }
- MonoReflectionMethodHandle
- ves_icall_RuntimeMethodInfo_get_base_method (MonoReflectionMethodHandle m, MonoBoolean definition, MonoError *error)
- {
- MonoMethod *method = MONO_HANDLE_GETVAL (m, method);
- MonoMethod *base = mono_method_get_base_method (method, definition, error);
- return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE));
- if (base == method) {
- /* we want to short-circuit and return 'm' here. But we should
- return the same method object that
- mono_method_get_object_handle, below would return. Since
- that call takes NULL for the reftype argument, it will take
- base->klass as the reflected type for the MonoMethod. So we
- need to check that m also has base->klass as the reflected
- type. */
- MonoReflectionTypeHandle orig_reftype = MONO_HANDLE_NEW_GET (MonoReflectionType, m, reftype);
- MonoClass *orig_klass = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (orig_reftype, type));
- if (base->klass == orig_klass)
- return m;
- }
- return mono_method_get_object_handle (mono_domain_get (), base, NULL, error);
- }
- MonoStringHandle
- ves_icall_RuntimeMethodInfo_get_name (MonoReflectionMethodHandle m, MonoError *error)
- {
- MonoMethod *method = MONO_HANDLE_GETVAL (m, method);
- MonoStringHandle s = mono_string_new_handle (MONO_HANDLE_DOMAIN (m), method->name, error);
- return_val_if_nok (error, NULL_HANDLE_STRING);
- MONO_HANDLE_SET (m, name, s);
- return s;
- }
- void
- ves_icall_System_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
- {
- iter->sig = *(MonoMethodSignature**)argsp;
-
- g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
- g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
- iter->next_arg = 0;
- /* FIXME: it's not documented what start is exactly... */
- if (start) {
- iter->args = start;
- } else {
- iter->args = argsp + sizeof (gpointer);
- }
- iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
- /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
- }
- void
- ves_icall_System_ArgIterator_IntGetNextArg (MonoArgIterator *iter, MonoTypedRef *res)
- {
- guint32 i, arg_size;
- gint32 align;
- i = iter->sig->sentinelpos + iter->next_arg;
- g_assert (i < iter->sig->param_count);
- res->type = iter->sig->params [i];
- res->klass = mono_class_from_mono_type_internal (res->type);
- arg_size = mono_type_stack_size (res->type, &align);
- #if defined(__arm__) || defined(__mips__)
- iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
- #endif
- res->value = iter->args;
- #if G_BYTE_ORDER != G_LITTLE_ENDIAN
- if (arg_size <= sizeof (gpointer)) {
- int dummy;
- int padding = arg_size - mono_type_size (res->type, &dummy);
- res->value = (guint8*)res->value + padding;
- }
- #endif
- iter->args = (char*)iter->args + arg_size;
- iter->next_arg++;
- /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res->type->type, arg_size, res->value); */
- }
- void
- ves_icall_System_ArgIterator_IntGetNextArgWithType (MonoArgIterator *iter, MonoTypedRef *res, MonoType *type)
- {
- guint32 i, arg_size;
- gint32 align;
- i = iter->sig->sentinelpos + iter->next_arg;
- g_assert (i < iter->sig->param_count);
- while (i < iter->sig->param_count) {
- if (!mono_metadata_type_equal (type, iter->sig->params [i]))
- continue;
- res->type = iter->sig->params [i];
- res->klass = mono_class_from_mono_type_internal (res->type);
- /* FIXME: endianess issue... */
- arg_size = mono_type_stack_size (res->type, &align);
- #if defined(__arm__) || defined(__mips__)
- iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
- #endif
- res->value = iter->args;
- iter->args = (char*)iter->args + arg_size;
- iter->next_arg++;
- /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
- return;
- }
- /* g_print ("arg type 0x%02x not found\n", res.type->type); */
- memset (res, 0, sizeof (MonoTypedRef));
- }
- MonoType*
- ves_icall_System_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
- {
- gint i;
-
- i = iter->sig->sentinelpos + iter->next_arg;
- g_assert (i < iter->sig->param_count);
- return iter->sig->params [i];
- }
- MonoObjectHandle
- ves_icall_System_TypedReference_ToObject (MonoTypedRef* tref, MonoError *error)
- {
- return typed_reference_to_object (tref, error);
- }
- void
- ves_icall_System_TypedReference_InternalMakeTypedReference (MonoTypedRef *res, MonoObjectHandle target, MonoArrayHandle fields, MonoReflectionTypeHandle last_field, MonoError *error)
- {
- MonoType *ftype = NULL;
- int i;
- memset (res, 0, sizeof (MonoTypedRef));
- g_assert (mono_array_handle_length (fields) > 0);
- (void)mono_handle_class (target);
- int offset = 0;
- for (i = 0; i < mono_array_handle_length (fields); ++i) {
- MonoClassField *f;
- MONO_HANDLE_ARRAY_GETVAL (f, fields, MonoClassField*, i);
- g_assert (f);
- if (i == 0)
- offset = f->offset;
- else
- offset += f->offset - sizeof (MonoObject);
- (void)mono_class_from_mono_type_internal (f->type);
- ftype = f->type;
- }
- res->type = ftype;
- res->klass = mono_class_from_mono_type_internal (ftype);
- res->value = (guint8*)MONO_HANDLE_RAW (target) + offset;
- }
- static void
- prelink_method (MonoMethod *method, MonoError *error)
- {
- error_init (error);
- if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
- return;
- mono_lookup_pinvoke_call_internal (method, error);
- /* create the wrapper, too? */
- }
- void
- ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethodHandle method, MonoError *error)
- {
- error_init (error);
- prelink_method (MONO_HANDLE_GETVAL (method, method), error);
- }
- void
- ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionTypeHandle type, MonoError *error);
- void
- ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionTypeHandle type, MonoError *error)
- {
- g_assert_not_netcore ();
- error_init (error);
- MonoClass *klass = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (type, type));
- MonoMethod* m;
- gpointer iter = NULL;
- mono_class_init_checked (klass, error);
- return_if_nok (error);
- while ((m = mono_class_get_methods (klass, &iter))) {
- prelink_method (m, error);
- return_if_nok (error);
- }
- }
- #ifndef ENABLE_NETCORE
- /*
- * used by System.Runtime.InteropServices.RuntimeInformation.(OS|Process)Architecture;
- * which use them in different ways for filling in an enum
- */
- MonoStringHandle
- ves_icall_System_Runtime_InteropServices_RuntimeInformation_GetRuntimeArchitecture (MonoError *error)
- {
- return mono_string_new_handle (mono_domain_get (), mono_config_get_cpu (), error);
- }
- /*
- * used by System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform
- */
- MonoStringHandle
- ves_icall_System_Runtime_InteropServices_RuntimeInformation_GetOSName (MonoError *error)
- {
- return mono_string_new_handle (mono_domain_get (), mono_config_get_os (), error);
- }
- #endif /* ENABLE_NETCORE */
- int
- ves_icall_Interop_Sys_DoubleToString(double value, char *format, char *buffer, int bufferLength)
- {
- #if defined(TARGET_ARM)
- /* workaround for faulty vcmp.f64 implementation on some 32bit ARM CPUs */
- guint64 bits = *(guint64 *) &value;
- if (bits == 0x1) { /* 4.9406564584124654E-324 */
- g_assert (!strcmp (format, "%.40e"));
- return snprintf (buffer, bufferLength, "%s", "4.9406564584124654417656879286822137236506e-324");
- } else if (bits == 0x4) { /* 2E-323 */
- g_assert (!strcmp (format, "%.40e"));
- return snprintf (buffer, bufferLength, "%s", "1.9762625833649861767062751714728854894602e-323");
- }
- #endif
- return snprintf(buffer, bufferLength, format, value);
- }
- void
- ves_icall_System_Runtime_RuntimeImports_ecvt_s(char *buffer, size_t sizeInBytes, double value, int count, int* dec, int* sign)
- {
- #if defined(TARGET_WIN32) || defined(HOST_WIN32)
- _ecvt_s(buffer, sizeInBytes, value, count, dec, sign);
- #endif
- }
- /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
- void
- ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
- gint32 const **exponents,
- gunichar2 const **digitLowerTable,
- gunichar2 const **digitUpperTable,
- gint64 const **tenPowersList,
- gint32 const **decHexDigits)
- {
- *mantissas = Formatter_MantissaBitsTable;
- *exponents = Formatter_TensExponentTable;
- *digitLowerTable = Formatter_DigitLowerTable;
- *digitUpperTable = Formatter_DigitUpperTable;
- *tenPowersList = Formatter_TenPowersList;
- *decHexDigits = Formatter_DecHexDigits;
- }
- static gboolean
- add_modifier_to_array (MonoDomain *domain, MonoType *type, MonoArrayHandle dest, int dest_idx, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- error_init (error);
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- MonoReflectionTypeHandle rt;
- rt = mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
- goto_if_nok (error, leave);
- MONO_HANDLE_ARRAY_SETREF (dest, dest_idx, rt);
- leave:
- HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
- }
- /*
- * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
- * and avoid useless allocations.
- */
- static MonoArrayHandle
- type_array_from_modifiers (MonoType *type, int optional, MonoError *error)
- {
- int i, count = 0;
- MonoDomain *domain = mono_domain_get ();
- int cmod_count = mono_type_custom_modifier_count (type);
- if (cmod_count == 0)
- goto fail;
- error_init (error);
- for (i = 0; i < cmod_count; ++i) {
- gboolean required;
- (void) mono_type_get_custom_modifier (type, i, &required, error);
- goto_if_nok (error, fail);
- if ((optional && !required) || (!optional && required))
- count++;
- }
- if (!count)
- goto fail;
- MonoArrayHandle res;
- res = mono_array_new_handle (domain, mono_defaults.systemtype_class, count, error);
- goto_if_nok (error, fail);
- count = 0;
- for (i = 0; i < cmod_count; ++i) {
- gboolean required;
- MonoType *cmod_type = mono_type_get_custom_modifier (type, i, &required, error);
- goto_if_nok (error, fail);
- if ((optional && !required) || (!optional && required)) {
- if (!add_modifier_to_array (domain, cmod_type, res, count, error))
- goto fail;
- count++;
- }
- }
- return res;
- fail:
- return MONO_HANDLE_NEW (MonoArray, NULL);
- }
- MonoArrayHandle
- ves_icall_RuntimeParameterInfo_GetTypeModifiers (MonoReflectionTypeHandle rt, MonoObjectHandle member, int pos, MonoBoolean optional, MonoError *error)
- {
- error_init (error);
- MonoType *type = MONO_HANDLE_GETVAL (rt, type);
- MonoClass *member_class = mono_handle_class (member);
- MonoMethod *method = NULL;
- MonoImage *image;
- MonoMethodSignature *sig;
- if (mono_class_is_reflection_method_or_constructor (member_class)) {
- method = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionMethod, member), method);
- } else if (m_class_get_image (member_class) == mono_defaults.corlib && !strcmp ("RuntimePropertyInfo", m_class_get_name (member_class))) {
- MonoProperty *prop = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionProperty, member), property);
- if (!(method = prop->get))
- method = prop->set;
- g_assert (method);
- } else if (strcmp (m_class_get_name (member_class), "DynamicMethod") == 0 && strcmp (m_class_get_name_space (member_class), "System.Reflection.Emit") == 0) {
- MonoArrayHandle params = MONO_HANDLE_NEW_GET (MonoArray, MONO_HANDLE_CAST (MonoReflectionDynamicMethod, member), parameters);
- MonoReflectionTypeHandle t = MONO_HANDLE_NEW (MonoReflectionType, NULL);
- MONO_HANDLE_ARRAY_GETREF (t, params, pos);
- type = mono_reflection_type_handle_mono_type (t, error);
- return type_array_from_modifiers (type, optional, error);
- } else {
- char *type_name = mono_type_get_full_name (member_class);
- mono_error_set_not_supported (error, "Custom modifiers on a ParamInfo with member %s are not supported", type_name);
- g_free (type_name);
- return NULL_HANDLE_ARRAY;
- }
- image = m_class_get_image (method->klass);
- sig = mono_method_signature_internal (method);
- if (pos == -1)
- type = sig->ret;
- else
- type = sig->params [pos];
- return type_array_from_modifiers (type, optional, error);
- }
- static MonoType*
- get_property_type (MonoProperty *prop)
- {
- MonoMethodSignature *sig;
- if (prop->get) {
- sig = mono_method_signature_internal (prop->get);
- return sig->ret;
- } else if (prop->set) {
- sig = mono_method_signature_internal (prop->set);
- return sig->params [sig->param_count - 1];
- }
- return NULL;
- }
- MonoArrayHandle
- ves_icall_RuntimePropertyInfo_GetTypeModifiers (MonoReflectionPropertyHandle property, MonoBoolean optional, MonoError *error)
- {
- error_init (error);
- MonoProperty *prop = MONO_HANDLE_GETVAL (property, property);
- MonoType *type = get_property_type (prop);
- if (!type)
- return NULL_HANDLE_ARRAY;
- return type_array_from_modifiers (type, optional, error);
- }
- /*
- *Construct a MonoType suited to be used to decode a constant blob object.
- *
- * @type is the target type which will be constructed
- * @blob_type is the blob type, for example, that comes from the constant table
- * @real_type is the expected constructed type.
- */
- static void
- mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
- {
- type->type = blob_type;
- type->data.klass = NULL;
- if (blob_type == MONO_TYPE_CLASS)
- type->data.klass = mono_defaults.object_class;
- else if (real_type->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (real_type->data.klass)) {
- /* For enums, we need to use the base type */
- type->type = MONO_TYPE_VALUETYPE;
- type->data.klass = mono_class_from_mono_type_internal (real_type);
- } else
- type->data.klass = mono_class_from_mono_type_internal (real_type);
- }
- MonoObjectHandle
- ves_icall_property_info_get_default_value (MonoReflectionPropertyHandle property_handle, MonoError* error)
- {
- MonoReflectionProperty* property = MONO_HANDLE_RAW (property_handle);
- MonoType blob_type;
- MonoProperty *prop = property->property;
- MonoType *type = get_property_type (prop);
- MonoDomain *domain = mono_object_domain (property);
- MonoTypeEnum def_type;
- const char *def_value;
- mono_class_init_internal (prop->parent);
- if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
- mono_error_set_invalid_operation (error, NULL);
- return NULL_HANDLE;
- }
- def_value = mono_class_get_property_default_value (prop, &def_type);
- mono_type_from_blob_type (&blob_type, def_type, type);
- return mono_get_object_from_blob (domain, &blob_type, def_value, MONO_HANDLE_NEW (MonoString, NULL), error);
- }
- MonoBoolean
- ves_icall_MonoCustomAttrs_IsDefinedInternal (MonoObjectHandle obj, MonoReflectionTypeHandle attr_type, MonoError *error)
- {
- MonoClass *attr_class = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (attr_type, type));
- mono_class_init_checked (attr_class, error);
- return_val_if_nok (error, FALSE);
- MonoCustomAttrInfo *cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
- return_val_if_nok (error, FALSE);
- if (!cinfo)
- return FALSE;
- gboolean found = mono_custom_attrs_has_attr (cinfo, attr_class);
- if (!cinfo->cached)
- mono_custom_attrs_free (cinfo);
- return found;
- }
- MonoArrayHandle
- ves_icall_MonoCustomAttrs_GetCustomAttributesInternal (MonoObjectHandle obj, MonoReflectionTypeHandle attr_type, MonoBoolean pseudoattrs, MonoError *error)
- {
- MonoClass *attr_class;
- if (MONO_HANDLE_IS_NULL (attr_type))
- attr_class = NULL;
- else
- attr_class = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (attr_type, type));
- if (attr_class) {
- mono_class_init_checked (attr_class, error);
- return_val_if_nok (error, NULL_HANDLE_ARRAY);
- }
- return mono_reflection_get_custom_attrs_by_type_handle (obj, attr_class, error);
- }
- MonoArrayHandle
- ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObjectHandle obj, MonoError *error)
- {
- return mono_reflection_get_custom_attrs_data_checked (obj, error);
- }
- MonoStringHandle
- ves_icall_Mono_Runtime_GetDisplayName (MonoError *error)
- {
- char *info;
- MonoStringHandle display_name;
- error_init (error);
- info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
- display_name = mono_string_new_handle (mono_domain_get (), info, error);
- g_free (info);
- return display_name;
- }
- #ifndef HOST_WIN32
- static gint32
- mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds)
- {
- return WAIT_TIMEOUT;
- }
- #endif /* !HOST_WIN32 */
- #ifndef ENABLE_NETCORE
- gint32
- ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
- {
- return mono_icall_wait_for_input_idle (handle, milliseconds);
- }
- gint32
- ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
- {
- return mono_process_current_pid ();
- }
- MonoBoolean
- ves_icall_Mono_TlsProviderFactory_IsBtlsSupported (void)
- {
- #if HAVE_BTLS
- return TRUE;
- #else
- return FALSE;
- #endif
- }
- #endif /* ENABLE_NETCORE */
- #ifndef DISABLE_COM
- int
- ves_icall_System_Runtime_InteropServices_Marshal_GetHRForException_WinRT(MonoExceptionHandle ex, MonoError *error)
- {
- mono_error_set_not_implemented (error, "System.Runtime.InteropServices.Marshal.GetHRForException_WinRT internal call is not implemented.");
- return 0;
- }
- MonoObjectHandle
- ves_icall_System_Runtime_InteropServices_Marshal_GetNativeActivationFactory(MonoObjectHandle type, MonoError *error)
- {
- mono_error_set_not_implemented (error, "System.Runtime.InteropServices.Marshal.GetNativeActivationFactory internal call is not implemented.");
- return NULL_HANDLE;
- }
- void*
- ves_icall_System_Runtime_InteropServices_Marshal_GetRawIUnknownForComObjectNoAddRef(MonoObjectHandle obj, MonoError *error)
- {
- mono_error_set_not_implemented (error, "System.Runtime.InteropServices.Marshal.GetRawIUnknownForComObjectNoAddRef internal call is not implemented.");
- return NULL;
- }
- MonoObjectHandle
- ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_GetRestrictedErrorInfo(MonoError *error)
- {
- mono_error_set_not_implemented (error, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.GetRestrictedErrorInfo internal call is not implemented.");
- return NULL_HANDLE;
- }
- MonoBoolean
- ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoOriginateLanguageException (int ierr, MonoStringHandle message, void* languageException, MonoError *error)
- {
- mono_error_set_not_implemented (error, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoOriginateLanguageException internal call is not implemented.");
- return FALSE;
- }
- void
- ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoReportUnhandledError (MonoObjectHandle oerr, MonoError *error)
- {
- mono_error_set_not_implemented (error, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoReportUnhandledError internal call is not implemented.");
- }
- int
- ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsCreateString(MonoStringHandle sourceString, int length, void** hstring, MonoError *error)
- {
- mono_error_set_not_implemented (error, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateString internal call is not implemented.");
- return 0;
- }
- int
- ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsDeleteString(void* hstring, MonoError *error)
- {
- mono_error_set_not_implemented (error, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsDeleteString internal call is not implemented.");
- return 0;
- }
- mono_unichar2*
- ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsGetStringRawBuffer(void* hstring, unsigned* length, MonoError *error)
- {
- mono_error_set_not_implemented (error, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsGetStringRawBuffer internal call is not implemented.");
- return NULL;
- }
- #endif
- #if !ENABLE_NETCORE
- void
- ves_icall_System_IO_LogcatTextWriter_Log (const char *appname, gint32 level, const char *message)
- {
- g_log (appname, (GLogLevelFlags)level, "%s", message);
- }
- #endif
- static const MonoIcallTableCallbacks *icall_table;
- static mono_mutex_t icall_mutex;
- static GHashTable *icall_hash = NULL;
- typedef struct _MonoIcallHashTableValue {
- gconstpointer method;
- guint32 flags;
- } MonoIcallHashTableValue;
- void
- mono_install_icall_table_callbacks (const MonoIcallTableCallbacks *cb)
- {
- g_assert (cb->version == MONO_ICALL_TABLE_CALLBACKS_VERSION);
- icall_table = cb;
- }
- void
- mono_icall_init (void)
- {
- #ifndef DISABLE_ICALL_TABLES
- mono_icall_table_init ();
- #endif
- icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
- mono_os_mutex_init (&icall_mutex);
- }
- static void
- mono_icall_lock (void)
- {
- mono_locks_os_acquire (&icall_mutex, IcallLock);
- }
- static void
- mono_icall_unlock (void)
- {
- mono_locks_os_release (&icall_mutex, IcallLock);
- }
- void
- mono_icall_cleanup (void)
- {
- g_hash_table_destroy (icall_hash);
- mono_os_mutex_destroy (&icall_mutex);
- }
- static void
- add_internal_call_with_flags (const char *name, gconstpointer method, guint32 flags)
- {
- char *key = g_strdup (name);
- MonoIcallHashTableValue *value = g_new (MonoIcallHashTableValue, 1);
- if (key && value) {
- value->method = method;
- value->flags = flags;
- mono_icall_lock ();
- g_hash_table_insert (icall_hash, key, (gpointer)value);
- mono_icall_unlock ();
- }
- }
- /**
- * mono_dangerous_add_internal_call_coop:
- * \param name method specification to surface to the managed world
- * \param method pointer to a C method to invoke when the method is called
- *
- * Similar to \c mono_dangerous_add_raw_internal_call.
- *
- */
- void
- mono_dangerous_add_internal_call_coop (const char *name, gconstpointer method)
- {
- add_internal_call_with_flags (name, method, MONO_ICALL_FLAGS_COOPERATIVE);
- }
- /**
- * mono_dangerous_add_internal_call_no_wrapper:
- * \param name method specification to surface to the managed world
- * \param method pointer to a C method to invoke when the method is called
- *
- * Similar to \c mono_dangerous_add_raw_internal_call but with more requirements for correct
- * operation.
- *
- * The \p method must NOT:
- *
- * Run for an unbounded amount of time without calling the mono runtime.
- * Additionally, the method must switch to GC Safe mode to perform all blocking
- * operations: performing blocking I/O, taking locks, etc. The method can't throw or raise
- * exceptions or call other methods that will throw or raise exceptions since the runtime won't
- * be able to detect exeptions and unwinder won't be able to correctly find last managed frame in callstack.
- * This registration method is for icalls that needs very low overhead and follow all rules in their implementation.
- *
- */
- void
- mono_dangerous_add_internal_call_no_wrapper (const char *name, gconstpointer method)
- {
- add_internal_call_with_flags (name, method, MONO_ICALL_FLAGS_NO_WRAPPER);
- }
- /**
- * mono_add_internal_call:
- * \param name method specification to surface to the managed world
- * \param method pointer to a C method to invoke when the method is called
- *
- * This method surfaces the C function pointed by \p method as a method
- * that has been surfaced in managed code with the method specified in
- * \p name as an internal call.
- *
- * Internal calls are surfaced to all app domains loaded and they are
- * accessibly by a type with the specified name.
- *
- * You must provide a fully qualified type name, that is namespaces
- * and type name, followed by a colon and the method name, with an
- * optional signature to bind.
- *
- * For example, the following are all valid declarations:
- *
- * \c MyApp.Services.ScriptService:Accelerate
- *
- * \c MyApp.Services.ScriptService:Slowdown(int,bool)
- *
- * You use method parameters in cases where there might be more than
- * one surface method to managed code. That way you can register different
- * internal calls for different method overloads.
- *
- * The internal calls are invoked with no marshalling. This means that .NET
- * types like \c System.String are exposed as \c MonoString* parameters. This is
- * different than the way that strings are surfaced in P/Invoke.
- *
- * For more information on how the parameters are marshalled, see the
- * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
- * page.
- *
- * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
- * reference for more information on the format of method descriptions.
- */
- void
- mono_add_internal_call (const char *name, gconstpointer method)
- {
- add_internal_call_with_flags (name, method, MONO_ICALL_FLAGS_FOREIGN);
- }
- /**
- * mono_dangerous_add_raw_internal_call:
- * \param name method specification to surface to the managed world
- * \param method pointer to a C method to invoke when the method is called
- *
- * Similar to \c mono_add_internal_call but with more requirements for correct
- * operation.
- *
- * A thread running a dangerous raw internal call will avoid a thread state
- * transition on entry and exit, but it must take responsiblity for cooperating
- * with the Mono runtime.
- *
- * The \p method must NOT:
- *
- * Run for an unbounded amount of time without calling the mono runtime.
- * Additionally, the method must switch to GC Safe mode to perform all blocking
- * operations: performing blocking I/O, taking locks, etc.
- *
- */
- void
- mono_dangerous_add_raw_internal_call (const char *name, gconstpointer method)
- {
- add_internal_call_with_flags (name, method, MONO_ICALL_FLAGS_COOPERATIVE);
- }
- /**
- * mono_add_internal_call_with_flags:
- * \param name method specification to surface to the managed world
- * \param method pointer to a C method to invoke when the method is called
- * \param cooperative if \c TRUE, run icall in GC Unsafe (cooperatively suspended) mode,
- * otherwise GC Safe (blocking)
- *
- * Like \c mono_add_internal_call, but if \p cooperative is \c TRUE the added
- * icall promises that it will use the coopertive API to inform the runtime
- * when it is running blocking operations, that it will not run for unbounded
- * amounts of time without safepointing, and that it will not hold managed
- * object references across suspend safepoints.
- *
- * If \p cooperative is \c FALSE, run the icall in GC Safe mode - the icall may
- * block. The icall must obey the GC Safe rules, e.g. it must not touch
- * unpinned managed memory.
- *
- */
- void
- mono_add_internal_call_with_flags (const char *name, gconstpointer method, gboolean cooperative)
- {
- add_internal_call_with_flags (name, method, cooperative ? MONO_ICALL_FLAGS_COOPERATIVE : MONO_ICALL_FLAGS_FOREIGN);
- }
- void
- mono_add_internal_call_internal (const char *name, gconstpointer method)
- {
- add_internal_call_with_flags (name, method, MONO_ICALL_FLAGS_COOPERATIVE);
- }
- /*
- * we should probably export this as an helper (handle nested types).
- * Returns the number of chars written in buf.
- */
- static int
- concat_class_name (char *buf, int bufsize, MonoClass *klass)
- {
- int nspacelen, cnamelen;
- nspacelen = strlen (m_class_get_name_space (klass));
- cnamelen = strlen (m_class_get_name (klass));
- if (nspacelen + cnamelen + 2 > bufsize)
- return 0;
- if (nspacelen) {
- memcpy (buf, m_class_get_name_space (klass), nspacelen);
- buf [nspacelen ++] = '.';
- }
- memcpy (buf + nspacelen, m_class_get_name (klass), cnamelen);
- buf [nspacelen + cnamelen] = 0;
- return nspacelen + cnamelen;
- }
- static void
- no_icall_table (void)
- {
- g_assert_not_reached ();
- }
- gboolean
- mono_is_missing_icall_addr (gconstpointer addr)
- {
- return addr == NULL || addr == no_icall_table;
- }
- /*
- * Returns either NULL or no_icall_table for missing icalls.
- */
- gconstpointer
- mono_lookup_internal_call_full_with_flags (MonoMethod *method, gboolean warn_on_missing, guint32 *flags)
- {
- char *sigstart = NULL;
- char *tmpsig = NULL;
- char mname [2048];
- char *classname = NULL;
- int typelen = 0, mlen, siglen;
- gconstpointer res = NULL;
- gboolean locked = FALSE;
- g_assert (method != NULL);
- if (method->is_inflated)
- method = ((MonoMethodInflated *) method)->declaring;
- if (m_class_get_nested_in (method->klass)) {
- int pos = concat_class_name (mname, sizeof (mname)-2, m_class_get_nested_in (method->klass));
- if (!pos)
- goto exit;
- mname [pos++] = '/';
- mname [pos] = 0;
- typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
- if (!typelen)
- goto exit;
- typelen += pos;
- } else {
- typelen = concat_class_name (mname, sizeof (mname), method->klass);
- if (!typelen)
- goto exit;
- }
- classname = g_strdup (mname);
- mname [typelen] = ':';
- mname [typelen + 1] = ':';
- mlen = strlen (method->name);
- memcpy (mname + typelen + 2, method->name, mlen);
- sigstart = mname + typelen + 2 + mlen;
- *sigstart = 0;
- tmpsig = mono_signature_get_desc (mono_method_signature_internal (method), TRUE);
- siglen = strlen (tmpsig);
- if (typelen + mlen + siglen + 6 > sizeof (mname))
- goto exit;
- sigstart [0] = '(';
- memcpy (sigstart + 1, tmpsig, siglen);
- sigstart [siglen + 1] = ')';
- sigstart [siglen + 2] = 0;
- /* mono_marshal_get_native_wrapper () depends on this */
- if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor")) {
- res = (gconstpointer)ves_icall_System_String_ctor_RedirectToCreateString;
- goto exit;
- }
- mono_icall_lock ();
- locked = TRUE;
- res = g_hash_table_lookup (icall_hash, mname);
- if (res) {
- MonoIcallHashTableValue *value = (MonoIcallHashTableValue *)res;
- if (flags)
- *flags = value->flags;
- res = value->method;
- goto exit;
- }
- /* try without signature */
- *sigstart = 0;
- res = g_hash_table_lookup (icall_hash, mname);
- if (res) {
- MonoIcallHashTableValue *value = (MonoIcallHashTableValue *)res;
- if (flags)
- *flags = value->flags;
- res = value->method;
- goto exit;
- }
- if (!icall_table) {
- /* Fail only when the result is actually used */
- res = (gconstpointer)no_icall_table;
- goto exit;
- } else {
- gboolean uses_handles = FALSE;
- g_assert (icall_table->lookup);
- res = icall_table->lookup (method, classname, sigstart - mlen, sigstart, &uses_handles);
- if (res && flags && uses_handles)
- *flags = *flags | MONO_ICALL_FLAGS_USES_HANDLES;
- mono_icall_unlock ();
- locked = FALSE;
- if (res)
- goto exit;
- if (warn_on_missing) {
- g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
- g_print ("\nYour mono runtime and class libraries are out of sync.\n");
- g_print ("The out of sync library is: %s\n", m_class_get_image (method->klass)->name);
- g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
- g_print ("Do not report this as a bug unless you're sure you have updated correctly:\nyou probably have a broken mono install.\n");
- g_print ("If you see other errors or faults after this message they are probably related\n");
- g_print ("and you need to fix your mono install first.\n");
- }
- res = NULL;
- }
- exit:
- if (locked)
- mono_icall_unlock ();
- g_free (classname);
- g_free (tmpsig);
- return res;
- }
- /**
- * mono_lookup_internal_call_full:
- * \param method the method to look up
- * \param uses_handles out argument if method needs handles around managed objects.
- * \returns a pointer to the icall code for the given method. If
- * \p uses_handles is not NULL, it will be set to TRUE if the method
- * needs managed objects wrapped using the infrastructure in handle.h
- *
- * If the method is not found, warns and returns NULL.
- */
- gconstpointer
- mono_lookup_internal_call_full (MonoMethod *method, gboolean warn_on_missing, mono_bool *uses_handles, mono_bool *foreign)
- {
- if (uses_handles)
- *uses_handles = FALSE;
- if (foreign)
- *foreign = FALSE;
- guint32 flags = MONO_ICALL_FLAGS_NONE;
- gconstpointer addr = mono_lookup_internal_call_full_with_flags (method, warn_on_missing, &flags);
- if (uses_handles && (flags & MONO_ICALL_FLAGS_USES_HANDLES))
- *uses_handles = TRUE;
- if (foreign && (flags & MONO_ICALL_FLAGS_FOREIGN))
- *foreign = TRUE;
- return addr;
- }
- /**
- * mono_lookup_internal_call:
- */
- gpointer
- mono_lookup_internal_call (MonoMethod *method)
- {
- return (gpointer)mono_lookup_internal_call_full (method, TRUE, NULL, NULL);
- }
- /*
- * mono_lookup_icall_symbol:
- *
- * Given the icall METHOD, returns its C symbol.
- */
- const char*
- mono_lookup_icall_symbol (MonoMethod *m)
- {
- if (!icall_table)
- return NULL;
- g_assert (icall_table->lookup_icall_symbol);
- gpointer func;
- func = (gpointer)mono_lookup_internal_call_full (m, FALSE, NULL, NULL);
- if (!func)
- return NULL;
- return icall_table->lookup_icall_symbol (func);
- }
- #if defined(TARGET_WIN32) && defined(TARGET_X86)
- /*
- * Under windows, the default pinvoke calling convention is STDCALL but
- * we need CDECL.
- */
- #define MONO_ICALL_SIGNATURE_CALL_CONVENTION MONO_CALL_C
- #else
- #define MONO_ICALL_SIGNATURE_CALL_CONVENTION 0
- #endif
- // Storage for these enums is pointer-sized as it gets replaced with MonoType*.
- //
- // mono_create_icall_signatures depends on this order. Handle with care.
- typedef enum ICallSigType {
- ICALL_SIG_TYPE_bool = 0x00,
- ICALL_SIG_TYPE_boolean = ICALL_SIG_TYPE_bool,
- ICALL_SIG_TYPE_double = 0x01,
- ICALL_SIG_TYPE_float = 0x02,
- ICALL_SIG_TYPE_int = 0x03,
- ICALL_SIG_TYPE_int16 = 0x04,
- ICALL_SIG_TYPE_int32 = ICALL_SIG_TYPE_int,
- ICALL_SIG_TYPE_int8 = 0x05,
- ICALL_SIG_TYPE_long = 0x06,
- ICALL_SIG_TYPE_obj = 0x07,
- ICALL_SIG_TYPE_object = ICALL_SIG_TYPE_obj,
- ICALL_SIG_TYPE_ptr = 0x08,
- ICALL_SIG_TYPE_ptrref = 0x09,
- ICALL_SIG_TYPE_string = 0x0A,
- ICALL_SIG_TYPE_uint16 = 0x0B,
- ICALL_SIG_TYPE_uint32 = 0x0C,
- ICALL_SIG_TYPE_uint8 = 0x0D,
- ICALL_SIG_TYPE_ulong = 0x0E,
- ICALL_SIG_TYPE_void = 0x0F,
- ICALL_SIG_TYPE_sizet = 0x10
- } ICallSigType;
- #define ICALL_SIG_TYPES_1(a) ICALL_SIG_TYPE_ ## a,
- #define ICALL_SIG_TYPES_2(a, b) ICALL_SIG_TYPES_1 (a ) ICALL_SIG_TYPES_1 (b)
- #define ICALL_SIG_TYPES_3(a, b, c) ICALL_SIG_TYPES_2 (a, b ) ICALL_SIG_TYPES_1 (c)
- #define ICALL_SIG_TYPES_4(a, b, c, d) ICALL_SIG_TYPES_3 (a, b, c ) ICALL_SIG_TYPES_1 (d)
- #define ICALL_SIG_TYPES_5(a, b, c, d, e) ICALL_SIG_TYPES_4 (a, b, c, d ) ICALL_SIG_TYPES_1 (e)
- #define ICALL_SIG_TYPES_6(a, b, c, d, e, f) ICALL_SIG_TYPES_5 (a, b, c, d, e) ICALL_SIG_TYPES_1 (f)
- #define ICALL_SIG_TYPES_7(a, b, c, d, e, f, g) ICALL_SIG_TYPES_6 (a, b, c, d, e, f) ICALL_SIG_TYPES_1 (g)
- #define ICALL_SIG_TYPES_8(a, b, c, d, e, f, g, h) ICALL_SIG_TYPES_7 (a, b, c, d, e, f, g) ICALL_SIG_TYPES_1 (h)
- #define ICALL_SIG_TYPES(n, types) ICALL_SIG_TYPES_ ## n types
- // A scheme to make these const would be nice.
- static struct {
- #define ICALL_SIG(n, xtypes) \
- struct { \
- MonoMethodSignature sig; \
- gsize types [n]; \
- } ICALL_SIG_NAME (n, xtypes);
- ICALL_SIGS
- MonoMethodSignature end; // terminal zeroed element
- } mono_icall_signatures = {
- #undef ICALL_SIG
- #define ICALL_SIG(n, types) { { \
- 0, /* ret */ \
- n, /* param_count */ \
- -1, /* sentinelpos */ \
- 0, /* generic_param_count */ \
- MONO_ICALL_SIGNATURE_CALL_CONVENTION, \
- 0, /* hasthis */ \
- 0, /* explicit_this */ \
- 1, /* pinvoke */ \
- 0, /* is_inflated */ \
- 0, /* has_type_parameters */ \
- }, /* possible gap here, depending on MONO_ZERO_LEN_ARRAY */ \
- { ICALL_SIG_TYPES (n, types) } }, /* params and ret */
- ICALL_SIGS
- };
- #undef ICALL_SIG
- #define ICALL_SIG(n, types) MonoMethodSignature * const ICALL_SIG_NAME (n, types) = &mono_icall_signatures.ICALL_SIG_NAME (n, types).sig;
- ICALL_SIGS
- #undef ICALL_SIG
- void
- mono_create_icall_signatures (void)
- {
- // Fixup the mostly statically initialized icall signatures.
- // x = m_class_get_byval_arg (x)
- // Initialize ret with params [0] and params [i] with params [i + 1].
- // ptrref is special
- //
- // FIXME This is a bit obscure.
- typedef MonoMethodSignature G_MAY_ALIAS MonoMethodSignature_a;
- typedef gsize G_MAY_ALIAS gsize_a;
- MonoType * const lookup [ ] = {
- m_class_get_byval_arg (mono_defaults.boolean_class), // ICALL_SIG_TYPE_bool
- m_class_get_byval_arg (mono_defaults.double_class), // ICALL_SIG_TYPE_double
- m_class_get_byval_arg (mono_defaults.single_class), // ICALL_SIG_TYPE_float
- m_class_get_byval_arg (mono_defaults.int32_class), // ICALL_SIG_TYPE_int
- m_class_get_byval_arg (mono_defaults.int16_class), // ICALL_SIG_TYPE_int16
- m_class_get_byval_arg (mono_defaults.sbyte_class), // ICALL_SIG_TYPE_int8
- m_class_get_byval_arg (mono_defaults.int64_class), // ICALL_SIG_TYPE_long
- m_class_get_byval_arg (mono_defaults.object_class), // ICALL_SIG_TYPE_obj
- m_class_get_byval_arg (mono_defaults.int_class), // ICALL_SIG_TYPE_ptr
- mono_class_get_byref_type (mono_defaults.int_class), // ICALL_SIG_TYPE_ptrref
- m_class_get_byval_arg (mono_defaults.string_class), // ICALL_SIG_TYPE_string
- m_class_get_byval_arg (mono_defaults.uint16_class), // ICALL_SIG_TYPE_uint16
- m_class_get_byval_arg (mono_defaults.uint32_class), // ICALL_SIG_TYPE_uint32
- m_class_get_byval_arg (mono_defaults.byte_class), // ICALL_SIG_TYPE_uint8
- m_class_get_byval_arg (mono_defaults.uint64_class), // ICALL_SIG_TYPE_ulong
- m_class_get_byval_arg (mono_defaults.void_class), // ICALL_SIG_TYPE_void
- m_class_get_byval_arg (mono_defaults.int_class), // ICALL_SIG_TYPE_sizet
- };
- MonoMethodSignature_a *sig = (MonoMethodSignature*)&mono_icall_signatures;
- int n;
- while ((n = sig->param_count)) {
- --sig->param_count; // remove ret
- gsize_a *types = (gsize_a*)(sig + 1);
- for (int i = 0; i < n; ++i) {
- gsize index = *types++;
- g_assert (index < G_N_ELEMENTS (lookup));
- // Casts on next line are attempt to follow strict aliasing rules,
- // to ensure reading from *types precedes writing
- // to params [].
- *(gsize*)(i ? &sig->params [i - 1] : &sig->ret) = (gsize)lookup [index];
- }
- sig = (MonoMethodSignature*)types;
- }
- }
- void
- mono_register_jit_icall_info (MonoJitICallInfo *info, gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean avoid_wrapper, const char *c_symbol)
- {
- // Duplicate initialization is allowed and racy, assuming it is equivalent.
- info->name = name;
- info->func = func;
- info->sig = sig;
- info->c_symbol = c_symbol;
- // Fill in wrapper ahead of time, to just be func, to avoid
- // later initializing it to anything else. So therefore, no wrapper.
- if (avoid_wrapper) {
- info->wrapper = func;
- } else {
- // Leave it alone in case of a race.
- }
- }
- int
- ves_icall_System_GC_GetCollectionCount (int generation)
- {
- return mono_gc_collection_count (generation);
- }
- int
- ves_icall_System_GC_GetGeneration (MonoObjectHandle object, MonoError *error)
- {
- return mono_gc_get_generation (MONO_HANDLE_RAW (object));
- }
- int
- ves_icall_System_GC_GetMaxGeneration (void)
- {
- return mono_gc_max_generation ();
- }
- gint64
- ves_icall_System_GC_GetAllocatedBytesForCurrentThread (void)
- {
- return mono_gc_get_allocated_bytes_for_current_thread ();
- }
- #ifdef ENABLE_NETCORE
- guint64
- ves_icall_System_GC_GetTotalAllocatedBytes (MonoBoolean precise, MonoError* error)
- {
- return mono_gc_get_total_allocated_bytes (precise);
- }
- #endif
- void
- ves_icall_System_GC_RecordPressure (gint64 value)
- {
- mono_gc_add_memory_pressure (value);
- }
- gint64
- ves_icall_System_Diagnostics_Stopwatch_GetTimestamp (void)
- {
- return mono_100ns_ticks ();
- }
- gint64
- ves_icall_System_Threading_Timer_GetTimeMonotonic (void)
- {
- return mono_100ns_ticks ();
- }
- gint64
- ves_icall_System_DateTime_GetSystemTimeAsFileTime (void)
- {
- return mono_100ns_datetime ();
- }
- int
- ves_icall_System_Threading_Thread_SystemMaxStackSize (void)
- {
- return mono_thread_info_get_system_max_stack_size ();
- }
- MonoBoolean
- ves_icall_System_Threading_Thread_YieldInternal (void)
- {
- mono_threads_platform_yield ();
- return TRUE;
- }
- gint32
- ves_icall_System_Environment_get_ProcessorCount (void)
- {
- return mono_cpu_count ();
- }
- #if !defined(ENABLE_NETCORE)
- #if defined(ENABLE_MONODROID)
- G_EXTERN_C gpointer CreateNLSocket (void);
- G_EXTERN_C gint32 ReadEvents (gpointer sock, gpointer buffer, gint32 count, gint32 size);
- G_EXTERN_C gpointer CloseNLSocket (gpointer sock);
- gpointer
- ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_CreateNLSocket (void)
- {
- return CreateNLSocket ();
- }
- gint32
- ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_ReadEvents (gpointer sock, gpointer buffer, gint32 count, gint32 size)
- {
- return ReadEvents (sock, buffer, count, size);
- }
- gpointer
- ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_CloseNLSocket (gpointer sock)
- {
- return CloseNLSocket (sock);
- }
- #endif
- #endif
- // Generate wrappers.
- #define ICALL_TYPE(id,name,first) /* nothing */
- #define ICALL(id,name,func) /* nothing */
- #define NOHANDLES(inner) /* nothing */
- #define MONO_HANDLE_REGISTER_ICALL(func, ret, nargs, argtypes) MONO_HANDLE_REGISTER_ICALL_IMPLEMENT (func, ret, nargs, argtypes)
- // Some native functions are exposed via multiple managed names.
- // Producing a wrapper for these results in duplicate wrappers with the same names,
- // which fails to compile. Do not produce such duplicate wrappers. Alternatively,
- // a one line native function with a different name that calls the main one could be used.
- // i.e. the wrapper would also have a different name.
- #define HANDLES_REUSE_WRAPPER(...) /* nothing */
- #define HANDLES(id, name, func, ret, nargs, argtypes) \
- MONO_HANDLE_DECLARE (id, name, func, ret, nargs, argtypes); \
- MONO_HANDLE_IMPLEMENT (id, name, func, ret, nargs, argtypes)
- #include "metadata/icall-def.h"
- #undef HANDLES
- #undef HANDLES_REUSE_WRAPPER
- #undef ICALL_TYPE
- #undef ICALL
- #undef NOHANDLES
- #undef MONO_HANDLE_REGISTER_ICALL
- MonoObjectHandle
- ves_icall_System_Threading_OSSpecificSynchronizationContext_GetOSContext ()
- {
- return NULL_HANDLE;
- }
- void
- ves_icall_System_Threading_OSSpecificSynchronizationContext_PostInternal (gpointer callback, gpointer arg)
- {
- /* This isn't actually reachable since ves_icall_System_Threading_OSSpecificSynchronizationContext_GetOSContext always returns NULL */
- mono_set_pending_exception (mono_exception_from_name_msg (mono_get_corlib (), "System", "NotImplementedException", "System.Threading.InteropServices.OSSpecificSynchronizationContext.PostInternal internal call is not implemented."));
- }
|