123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406 |
- (*
- * This file is part of ilLib
- * Copyright (c)2004-2013 Haxe Foundation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- *)
- open PeData;;
- open PeReader;;
- open IlMeta;;
- open IO;;
- open Printf;;
- open IlMetaTools;;
- open ExtString;;
- open IlData;;
- (* *)
- let get_field = function
- | Field f -> f
- | _ -> assert false
- let get_method = function
- | Method m -> m
- | _ -> assert false
- let get_param = function
- | Param p -> p
- | _ -> assert false
- let get_type_def = function
- | TypeDef p -> p
- | _ -> assert false
- let get_event = function
- | Event e -> e
- | _ -> assert false
- let get_property = function
- | Property p -> p
- | _ -> assert false
- let get_module_ref = function
- | ModuleRef r -> r
- | _ -> assert false
- let get_assembly_ref = function
- | AssemblyRef r -> r
- | _ -> assert false
- let get_generic_param = function
- | GenericParam p -> p
- | _ -> assert false
- (* decoding helpers *)
- let type_def_vis_of_int i = match i land 0x7 with
- (* visibility flags - mask 0x7 *)
- | 0x0 -> VPrivate (* 0x0 *)
- | 0x1 -> VPublic (* 0x1 *)
- | 0x2 -> VNestedPublic (* 0x2 *)
- | 0x3 -> VNestedPrivate (* 0x3 *)
- | 0x4 -> VNestedFamily (* 0x4 *)
- | 0x5 -> VNestedAssembly (* 0x5 *)
- | 0x6 -> VNestedFamAndAssem (* 0x6 *)
- | 0x7 -> VNestedFamOrAssem (* 0x7 *)
- | _ -> assert false
- let type_def_layout_of_int i = match i land 0x18 with
- (* layout flags - mask 0x18 *)
- | 0x0 -> LAuto (* 0x0 *)
- | 0x8 -> LSequential (* 0x8 *)
- | 0x10 -> LExplicit (* 0x10 *)
- | _ -> assert false
- let type_def_semantics_of_int iprops = List.fold_left (fun acc i ->
- if (iprops land i) = i then (match i with
- (* semantics flags - mask 0x5A0 *)
- | 0x20 -> SInterface (* 0x20 *)
- | 0x80 -> SAbstract (* 0x80 *)
- | 0x100 -> SSealed (* 0x100 *)
- | 0x400 -> SSpecialName (* 0x400 *)
- | _ -> assert false) :: acc
- else
- acc) [] [0x20;0x80;0x100;0x400]
- let type_def_impl_of_int iprops = List.fold_left (fun acc i ->
- if (iprops land i) = i then (match i with
- (* type implementation flags - mask 0x103000 *)
- | 0x1000 -> IImport (* 0x1000 *)
- | 0x2000 -> ISerializable (* 0x2000 *)
- | 0x00100000 -> IBeforeFieldInit (* 0x00100000 *)
- | _ -> assert false) :: acc
- else
- acc) [] [0x1000;0x2000;0x00100000]
- let type_def_string_of_int i = match i land 0x00030000 with
- (* string formatting flags - mask 0x00030000 *)
- | 0x0 -> SAnsi (* 0x0 *)
- | 0x00010000 -> SUnicode (* 0x00010000 *)
- | 0x00020000 -> SAutoChar (* 0x00020000 *)
- | _ -> assert false
- let type_def_flags_of_int i =
- {
- tdf_vis = type_def_vis_of_int i;
- tdf_layout = type_def_layout_of_int i;
- tdf_semantics = type_def_semantics_of_int i;
- tdf_impl = type_def_impl_of_int i;
- tdf_string = type_def_string_of_int i;
- }
- let null_type_def_flags = type_def_flags_of_int 0
- let field_access_of_int i = match i land 0x07 with
- (* access flags - mask 0x07 *)
- | 0x0 -> FAPrivateScope (* 0x0 *)
- | 0x1 -> FAPrivate (* 0x1 *)
- | 0x2 -> FAFamAndAssem (* 0x2 *)
- | 0x3 -> FAAssembly (* 0x3 *)
- | 0x4 -> FAFamily (* 0x4 *)
- | 0x5 -> FAFamOrAssem (* 0x5 *)
- | 0x6 -> FAPublic (* 0x6 *)
- | _ -> assert false
- let field_contract_of_int iprops = List.fold_left (fun acc i ->
- if (iprops land i) = i then (match i with
- (* contract flags - mask 0x02F0 *)
- | 0x10 -> CStatic (* 0x10 *)
- | 0x20 -> CInitOnly (* 0x20 *)
- | 0x40 -> CLiteral (* 0x40 *)
- | 0x80 -> CNotSerialized (* 0x80 *)
- | 0x200 -> CSpecialName (* 0x200 *)
- | _ -> assert false) :: acc
- else
- acc) [] [0x10;0x20;0x40;0x80;0x200]
- let field_reserved_of_int iprops = List.fold_left (fun acc i ->
- if (iprops land i) = i then (match i with
- (* reserved flags - cannot be set explicitly. mask 0x9500 *)
- | 0x400 -> RSpecialName (* 0x400 *)
- | 0x1000 -> RMarshal (* 0x1000 *)
- | 0x8000 -> RConstant (* 0x8000 *)
- | 0x0100 -> RFieldRVA (* 0x0100 *)
- | _ -> assert false) :: acc
- else
- acc) [] [0x400;0x1000;0x8000;0x100]
- let field_flags_of_int i =
- {
- ff_access = field_access_of_int i;
- ff_contract = field_contract_of_int i;
- ff_reserved = field_reserved_of_int i;
- }
- let null_field_flags = field_flags_of_int 0
- let method_contract_of_int iprops = List.fold_left (fun acc i ->
- if (iprops land i) = i then (match i with
- (* contract flags - mask 0xF0 *)
- | 0x10 -> CMStatic (* 0x10 *)
- | 0x20 -> CMFinal (* 0x20 *)
- | 0x40 -> CMVirtual (* 0x40 *)
- | 0x80 -> CMHideBySig (* 0x80 *)
- | _ -> assert false) :: acc
- else
- acc) [] [0x10;0x20;0x40;0x80]
- let method_vtable_of_int iprops = List.fold_left (fun acc i ->
- if (iprops land i) = i then (match i with
- (* vtable flags - mask 0x300 *)
- | 0x100 -> VNewSlot (* 0x100 *)
- | 0x200 -> VStrict (* 0x200 *)
- | _ -> assert false) :: acc
- else
- acc) [] [0x100;0x200]
- let method_impl_of_int iprops = List.fold_left (fun acc i ->
- if (iprops land i) = i then (match i with
- (* implementation flags - mask 0x2C08 *)
- | 0x0400 -> IAbstract (* 0x0400 *)
- | 0x0800 -> ISpecialName (* 0x0800 *)
- | 0x2000 -> IPInvokeImpl (* 0x2000 *)
- | 0x0008 -> IUnmanagedExp (* 0x0008 *)
- | _ -> assert false) :: acc
- else
- acc) [] [0x0400;0x0800;0x2000;0x0008]
- let method_reserved_of_int iprops = List.fold_left (fun acc i ->
- if (iprops land i) = i then (match i with
- (* reserved flags - cannot be set explicitly. mask 0xD000 *)
- | 0x1000 -> RTSpecialName (* 0x1000 *)
- | 0x4000 -> RHasSecurity (* 0x4000 *)
- | 0x8000 -> RReqSecObj (* 0x8000 *)
- | _ -> assert false) :: acc
- else
- acc) [] [0x1000;0x4000;0x8000]
- let method_code_type_of_int i = match i land 0x3 with
- | 0x0 -> CCil (* 0x0 *)
- | 0x1 -> CNative (* 0x1 *)
- | 0x2 -> COptIl (* 0x2 *)
- | 0x3 -> CRuntime (* 0x3 *)
- | _ -> assert false
- let method_code_mngmt_of_int i = match i land 0x4 with
- | 0x0 -> MManaged (* 0x0 *)
- | 0x4 -> MUnmanaged (* 0x4 *)
- | _ -> assert false
- let method_interop_of_int iprops = List.fold_left (fun acc i ->
- if (iprops land i) = i then (match i with
- | 0x10 -> OForwardRef (* 0x10 *)
- | 0x80 -> OPreserveSig (* 0x80 *)
- | 0x1000 -> OInternalCall (* 0x1000 *)
- | 0x20 -> OSynchronized (* 0x20 *)
- | 0x08 -> ONoInlining (* 0x08 *)
- | _ -> assert false) :: acc
- else
- acc) [] [0x10;0x80;0x1000;0x20;0x08]
- let method_flags_of_int iflags flags =
- {
- mf_access = field_access_of_int flags;
- mf_contract = method_contract_of_int flags;
- mf_vtable = method_vtable_of_int flags;
- mf_impl = method_impl_of_int flags;
- mf_reserved = method_reserved_of_int flags;
- mf_code_type = method_code_type_of_int iflags;
- mf_code_mngmt = method_code_mngmt_of_int iflags;
- mf_interop = method_interop_of_int iflags;
- }
- let null_method_flags = method_flags_of_int 0 0
- let param_io_of_int iprops = List.fold_left (fun acc i ->
- if (iprops land i) = i then (match i with
- (* input/output flags - mask 0x13 *)
- | 0x1 -> PIn (* 0x1 *)
- | 0x2 -> POut (* 0x2 *)
- | 0x10 -> POpt (* 0x10 *)
- | _ -> assert false) :: acc
- else
- acc) [] [0x1;0x2;0x10]
- let param_reserved_of_int iprops = List.fold_left (fun acc i ->
- if (iprops land i) = i then (match i with
- (* reserved flags - mask 0xF000 *)
- | 0x1000 -> PHasConstant (* 0x1000 *)
- | 0x2000 -> PMarshal (* 0x2000 *)
- | _ -> assert false) :: acc
- else
- acc) [] [0x1000;0x2000]
- let param_flags_of_int i =
- {
- pf_io = param_io_of_int i;
- pf_reserved = param_reserved_of_int i;
- }
- let null_param_flags = param_flags_of_int 0
- let callconv_of_int ?match_generic_inst:(match_generic_inst=false) i =
- let basic = match i land 0xF with
- | 0x0 -> CallDefault (* 0x0 *)
- | 0x1 -> CallCDecl
- | 0x2 -> CallStdCall
- | 0x3 -> CallThisCall
- | 0x4 -> CallFastCall
- | 0x5 -> CallVararg (* 0x5 *)
- | 0x6 -> CallField (* 0x6 *)
- | 0x7 -> CallLocal (* 0x7 *)
- | 0x8 -> CallProp (* 0x8 *)
- | 0x9 -> CallUnmanaged (* 0x9 *)
- | 0xa when match_generic_inst -> CallGenericInst (* 0xA *)
- | i -> printf "error 0x%x\n\n" i; assert false
- in
- match i land 0x20 with
- | 0x20 ->
- [CallHasThis;basic]
- | _ when i land 0x40 = 0x40 ->
- [CallExplicitThis;basic]
- | _ -> [basic]
- let event_flags_of_int iprops = List.fold_left (fun acc i ->
- if (iprops land i) = i then (match i with
- | 0x0200 -> ESpecialName (* 0x0200 *)
- | 0x0400 -> ERTSpecialName (* 0x0400 *)
- | _ -> assert false) :: acc
- else
- acc) [] [0x0200;0x0400]
- let property_flags_of_int iprops = List.fold_left (fun acc i ->
- if (iprops land i) = i then (match i with
- | 0x0200 -> PSpecialName (* 0x0200 *)
- | 0x0400 -> PRTSpecialName (* 0x0400 *)
- | 0x1000 -> PHasDefault (* 0x1000 *)
- | 0xE9FF -> PUnused (* 0xE9FF *)
- | _ -> assert false) :: acc
- else
- acc) [] [0x0200;0x0400;0x1000;0xE9FF]
- let semantic_flags_of_int iprops = List.fold_left (fun acc i ->
- if (iprops land i) = i then (match i with
- | 0x0001 -> SSetter (* 0x0001 *)
- | 0x0002 -> SGetter (* 0x0002 *)
- | 0x0004 -> SOther (* 0x0004 *)
- | 0x0008 -> SAddOn (* 0x0008 *)
- | 0x0010 -> SRemoveOn (* 0x0010 *)
- | 0x0020 -> SFire (* 0x0020 *)
- | _ -> assert false) :: acc
- else
- acc) [] [0x0001;0x0002;0x0004;0x0008;0x0010;0x0020]
- let impl_charset_of_int = function
- | 0x0 -> IDefault (* 0x0 *)
- | 0x2 -> IAnsi (* 0x2 *)
- | 0x4 -> IUnicode (* 0x4 *)
- | 0x6 -> IAutoChar (* 0x6 *)
- | _ -> assert false
- let impl_callconv_of_int = function
- | 0x0 -> IDefaultCall (* 0x0 *)
- | 0x100 -> IWinApi (* 0x100 *)
- | 0x200 -> ICDecl (* 0x200 *)
- | 0x300 -> IStdCall (* 0x300 *)
- | 0x400 -> IThisCall (* 0x400 *)
- | 0x500 -> IFastCall (* 0x500 *)
- | _ -> assert false
- let impl_flag_of_int iprops = List.fold_left (fun acc i ->
- if (iprops land i) = i then (match i with
- | 0x1 -> INoMangle (* 0x1 *)
- | 0x10 -> IBestFit (* 0x10 *)
- | 0x20 -> IBestFitOff (* 0x20 *)
- | 0x40 -> ILastErr (* 0x40 *)
- | 0x1000 -> ICharMapError (* 0x1000 *)
- | 0x2000 -> ICharMapErrorOff (* 0x2000 *)
- | _ -> assert false) :: acc
- else
- acc) [] [0x1;0x10;0x20;0x40;0x1000;0x2000]
- let impl_flags_of_int i =
- {
- if_charset = impl_charset_of_int (i land 0x6);
- if_callconv = impl_callconv_of_int (i land 0x700);
- if_flags = impl_flag_of_int i;
- }
- let null_impl_flags = impl_flags_of_int 0
- let assembly_flags_of_int iprops = List.fold_left (fun acc i ->
- if (iprops land i) = i then (match i with
- | 0x1 -> APublicKey (* 0x1 *)
- | 0x100 -> ARetargetable (* 0x100 *)
- | 0x4000 -> ADisableJitCompileOptimizer (* 0x4000 *)
- | 0x8000 -> AEnableJitCompileTracking (* 0x8000 *)
- | _ -> assert false) :: acc
- else
- acc) [] [0x1;0x100;0x4000;0x8000]
- let hash_algo_of_int = function
- | 0x0 -> HNone (* 0x0 *)
- | 0x8003 -> HReserved (* 0x8003 *)
- | 0x8004 -> HSha1 (* 0x8004 *)
- | _ -> assert false
- let file_flag_of_int = function
- | 0x0 -> ContainsMetadata (* 0x0 *)
- | 0x1 -> ContainsNoMetadata (* 0x1 *)
- | _ -> assert false
- let manifest_resource_flag_of_int i = match i land 0x7 with
- | 0x0 -> RNone (* 0x0 *)
- | 0x1 -> RPublic (* 0x1 *)
- | 0x2 -> RPrivate (* 0x2 *)
- | _ -> assert false
- let generic_variance_of_int = function
- (* mask 0x3 *)
- | 0x0 -> VNone (* 0x0 *)
- | 0x1 -> VCovariant (* 0x1 *)
- | 0x2 -> VContravariant (* 0x2 *)
- | _ -> assert false
- let generic_constraint_of_int iprops = List.fold_left (fun acc i ->
- if (iprops land i) = i then (match i with
- (* mask 0x1C *)
- | 0x4 -> CInstanceType (* 0x4 *)
- | 0x8 -> CValueType (* 0x8 *)
- | 0x10 -> CDefaultCtor (* 0x10 *)
- | _ -> assert false) :: acc
- else
- acc) [] [0x4;0x8;0x10]
- let generic_flags_of_int i =
- {
- gf_variance = generic_variance_of_int (i land 0x3);
- gf_constraint = generic_constraint_of_int (i land 0x1C);
- }
- let null_generic_flags = generic_flags_of_int 0
- (* TODO: convert from string to Bigstring if OCaml 4 is available *)
- type meta_ctx = {
- compressed : bool;
- (* is a compressed stream *)
- strings_stream : string;
- mutable strings_offset : int;
- (* #Strings: a string heap containing the names of metadata items *)
- blob_stream : string;
- mutable blob_offset : int;
- (* #Blob: blob heap containing internal metadata binary object, such as default values, signatures, etc *)
- guid_stream : string;
- mutable guid_offset : int;
- (* #GUID: a GUID heap *)
- us_stream : string;
- (* #US: user-defined strings *)
- meta_stream : string;
- (* may be either: *)
- (* #~: compressed (optimized) metadata stream *)
- (* #-: uncompressed (unoptimized) metadata stream *)
- mutable meta_edit_continue : bool;
- mutable meta_has_deleted : bool;
- module_cache : meta_cache;
- tables : (clr_meta DynArray.t) array;
- table_sizes : ( string -> int -> int * int ) array;
- extra_streams : clr_stream_header list;
- relations : (meta_pointer, clr_meta) Hashtbl.t;
- typedefs : (ilpath, meta_type_def) Hashtbl.t;
- mutable delays : (unit -> unit) list;
- }
- and meta_cache = {
- mutable lookups : (string -> meta_ctx option) list;
- mutable mcache : (meta_module * meta_ctx) list;
- }
- let empty = "<not initialized>"
- let create_cache () =
- {
- lookups = [];
- mcache = [];
- }
- let add_lookup cache fn =
- cache.lookups <- fn :: cache.lookups
- (* ******* Reading from Strings ********* *)
- let sget s pos = Char.code (String.get s pos)
- let read_compressed_i32 s pos =
- let v = sget s pos in
- (* Printf.printf "compressed: %x (18 0x%x 19 0x%x)\n" v (sget s (pos+20)) (sget s (pos+21)); *)
- if v land 0x80 = 0x00 then
- pos+1, v
- else if v land 0xC0 = 0x80 then
- pos+2, ((v land 0x3F) lsl 8) lor (sget s (pos+1))
- else if v land 0xE0 = 0xC0 then
- pos+4, ((v land 0x1F) lsl 24) lor ((sget s (pos+1)) lsl 16) lor ((sget s (pos+2)) lsl 8) lor (sget s (pos+3))
- else
- error (Printf.sprintf "Error reading compressed data. Invalid first byte: %x" v)
- let int_of_table (idx : clr_meta_idx) : int = Obj.magic idx
- let table_of_int (idx : int) : clr_meta_idx = Obj.magic idx
- let sread_ui8 s pos =
- let n1 = sget s pos in
- pos+1,n1
- let sread_i32 s pos =
- let n1 = sget s pos in
- let n2 = sget s (pos+1) in
- let n3 = sget s (pos+2) in
- let n4 = sget s (pos+3) in
- pos+4, (n4 lsl 24) lor (n3 lsl 16) lor (n2 lsl 8) lor n1
- let sread_real_i32 s pos =
- let n1 = sget s pos in
- let n2 = sget s (pos+1) in
- let n3 = sget s (pos+2) in
- let n4 = Int32.of_int (sget s (pos+3)) in
- let n = Int32.of_int ((n3 lsl 16) lor (n2 lsl 8) lor n1) in
- let n4 = Int32.shift_left n4 24 in
- pos+4, (Int32.logor n4 n)
- let sread_i64 s pos =
- let pos, v1 = sread_real_i32 s (pos+1) in
- let v1 = Int64.of_int32 v1 in
- let pos, v2 = sread_real_i32 s pos in
- let v2 = Int64.of_int32 v2 in
- let v2 = Int64.shift_left v2 32 in
- pos, (Int64.logor v1 v2)
- let sread_ui16 s pos =
- let n1 = sget s pos in
- let n2 = sget s (pos+1) in
- pos+2, (n2 lsl 8) lor n1
- let read_cstring ctx pos =
- let s = ctx.strings_stream in
- let rec loop en =
- match String.get s en with
- | '\x00' -> en - pos
- | _ -> loop (en+1)
- in
- (* printf "len 0x%x - pos 0x%x\n" (String.length s) pos; *)
- let len = loop pos in
- String.sub s pos len
- let read_sstring_idx ctx pos =
- let s = ctx.meta_stream in
- let metapos,i = if ctx.strings_offset = 2 then
- sread_ui16 s pos
- else
- sread_i32 s pos
- in
- match i with
- | 0 ->
- metapos, ""
- | _ ->
- metapos, read_cstring ctx i
- let read_sblob_idx ctx pos =
- let s = ctx.meta_stream in
- let metapos, i = if ctx.blob_offset = 2 then
- sread_ui16 s pos
- else
- sread_i32 s pos
- in
- match i with
- | 0 ->
- metapos,""
- | _ ->
- let bpos, len = read_compressed_i32 ctx.blob_stream i in
- metapos, String.sub ctx.blob_stream bpos len
- let read_sguid_idx ctx pos =
- let s = ctx.meta_stream in
- let metapos,i = if ctx.guid_offset = 2 then
- sread_ui16 s pos
- else
- sread_i32 s pos
- in
- match i with
- | 0 ->
- metapos, ""
- | _ ->
- let s = ctx.guid_stream in
- let i = i - 1 in
- let pos = i * 16 in
- metapos, String.sub s pos 16
- let read_callconv ctx s pos =
- let pos, conv = read_compressed_i32 s pos in
- let callconv = callconv_of_int conv ~match_generic_inst:true in
- let pos = match conv land 0x10 with
- | 0x10 -> fst (read_compressed_i32 s pos)
- | _ -> pos
- in
- pos, callconv
- let read_constant ctx with_type s pos =
- match with_type with
- | CBool ->
- pos+1, IBool (sget s (pos) <> 0)
- | CChar ->
- let pos, v = sread_ui16 s (pos) in
- pos, IChar v
- | CInt8 | CUInt8 ->
- pos+1,IByte (sget s (pos))
- | CInt16 | CUInt16 ->
- let pos, v = sread_ui16 s (pos) in
- pos, IShort v
- | CInt32 | CUInt32 ->
- let pos, v = sread_real_i32 s (pos) in
- pos, IInt v
- | CInt64 | CUInt64 ->
- let pos, v = sread_i64 s (pos) in
- pos, IInt64 v
- | CFloat32 ->
- let pos, v1 = sread_real_i32 s (pos) in
- pos, IFloat32 (Int32.float_of_bits v1)
- | CFloat64 ->
- let pos, v1 = sread_i64 s (pos) in
- pos, IFloat64 (Int64.float_of_bits v1)
- | CString ->
- if sget s pos = 0xff then
- pos+1,IString ""
- else
- let pos, len = read_compressed_i32 s pos in
- pos+len, IString (String.sub s pos len)
- | CNullRef ->
- pos+1, INull
- let sig_to_const = function
- | SBool -> CBool
- | SChar -> CChar
- | SInt8 -> CInt8
- | SUInt8 -> CUInt8
- | SInt16 -> CInt16
- | SUInt16 -> CUInt16
- | SInt32 -> CInt32
- | SUInt32 -> CUInt32
- | SInt64 -> CInt64
- | SUInt64 -> CUInt64
- | SFloat32 -> CFloat32
- | SFloat64 -> CFloat64
- | SString -> CString
- | _ -> CNullRef
- let read_constant_type ctx s pos = match sget s pos with
- | 0x2 -> pos+1, CBool (* 0x2 *)
- | 0x3 -> pos+1, CChar (* 0x3 *)
- | 0x4 -> pos+1, CInt8 (* 0x4 *)
- | 0x5 -> pos+1, CUInt8 (* 0x5 *)
- | 0x6 -> pos+1, CInt16 (* 0x6 *)
- | 0x7 -> pos+1, CUInt16 (* 0x7 *)
- | 0x8 -> pos+1, CInt32 (* 0x8 *)
- | 0x9 -> pos+1, CUInt32 (* 0x9 *)
- | 0xA -> pos+1, CInt64 (* 0xA *)
- | 0xB -> pos+1, CUInt64 (* 0xB *)
- | 0xC -> pos+1, CFloat32 (* 0xC *)
- | 0xD -> pos+1, CFloat64 (* 0xD *)
- | 0xE -> pos+1, CString (* 0xE *)
- | 0x12 -> pos+1, CNullRef (* 0x12 *)
- | i -> Printf.printf "0x%x\n" i; assert false
- let action_security_of_int = function
- | 0x1 -> SecRequest (* 0x1 *)
- | 0x2 -> SecDemand (* 0x2 *)
- | 0x3 -> SecAssert (* 0x3 *)
- | 0x4 -> SecDeny (* 0x4 *)
- | 0x5 -> SecPermitOnly (* 0x5 *)
- | 0x6 -> SecLinkCheck (* 0x6 *)
- | 0x7 -> SecInheritCheck (* 0x7 *)
- | 0x8 -> SecReqMin (* 0x8 *)
- | 0x9 -> SecReqOpt (* 0x9 *)
- | 0xA -> SecReqRefuse (* 0xA *)
- | 0xB -> SecPreJitGrant (* 0xB *)
- | 0xC -> SecPreJitDeny (* 0xC *)
- | 0xD -> SecNonCasDemand (* 0xD *)
- | 0xE -> SecNonCasLinkDemand (* 0xE *)
- | 0xF -> SecNonCasInheritance (* 0xF *)
- | _ -> assert false
- (* ******* Metadata Tables ********* *)
- let null_meta = UnknownMeta (-1)
- let mk_module id =
- {
- md_id = id;
- md_generation = 0;
- md_name = empty;
- md_vid = empty;
- md_encid = empty;
- md_encbase_id = empty;
- }
- let null_module = mk_module (-1)
- let mk_type_ref id =
- {
- tr_id = id;
- tr_resolution_scope = null_meta;
- tr_name = empty;
- tr_namespace = [];
- }
- let null_type_ref = mk_type_ref (-1)
- let mk_type_def id =
- {
- td_id = id;
- td_flags = null_type_def_flags;
- td_name = empty;
- td_namespace = [];
- td_extends = None;
- td_field_list = [];
- td_method_list = [];
- td_extra_enclosing = None;
- }
- let null_type_def = mk_type_def (-1)
- let mk_field id =
- {
- f_id = id;
- f_flags = null_field_flags;
- f_name = empty;
- f_signature = SVoid;
- }
- let null_field = mk_field (-1)
- let mk_field_ptr id =
- {
- fp_id = id;
- fp_field = null_field;
- }
- let null_field_ptr = mk_field_ptr (-1)
- let mk_method id =
- {
- m_id = id;
- m_rva = Int32.of_int (-1);
- m_flags = null_method_flags;
- m_name = empty;
- m_signature = SVoid;
- m_param_list = [];
- m_declaring = None;
- }
- let null_method = mk_method (-1)
- let mk_method_ptr id =
- {
- mp_id = id;
- mp_method = null_method;
- }
- let null_method_ptr = mk_method_ptr (-1)
- let mk_param id =
- {
- p_id = id;
- p_flags = null_param_flags;
- p_sequence = -1;
- p_name = empty;
- }
- let null_param = mk_param (-1)
- let mk_param_ptr id =
- {
- pp_id = id;
- pp_param = null_param;
- }
- let null_param_ptr = mk_param_ptr (-1)
- let mk_interface_impl id =
- {
- ii_id = id;
- ii_class = null_type_def; (* TypeDef rid *)
- ii_interface = null_meta;
- }
- let null_interface_impl = mk_interface_impl (-1)
- let mk_member_ref id =
- {
- memr_id = id;
- memr_class = null_meta;
- memr_name = empty;
- memr_signature = SVoid;
- }
- let null_member_ref = mk_member_ref (-1)
- let mk_constant id =
- {
- c_id = id;
- c_type = CNullRef;
- c_parent = null_meta;
- c_value = INull;
- }
- let null_constant = mk_constant (-1)
- let mk_custom_attribute id =
- {
- ca_id = id;
- ca_parent = null_meta;
- ca_type = null_meta;
- ca_value = None;
- }
- let null_custom_attribute = mk_custom_attribute (-1)
- let mk_field_marshal id =
- {
- fm_id = id;
- fm_parent = null_meta;
- fm_native_type = NVoid;
- }
- let null_field_marshal = mk_field_marshal (-1)
- let mk_decl_security id =
- {
- ds_id = id;
- ds_action = SecNull;
- ds_parent = null_meta;
- ds_permission_set = empty;
- }
- let mk_class_layout id =
- {
- cl_id = id;
- cl_packing_size = -1;
- cl_class_size = -1;
- cl_parent = null_type_def;
- }
- let mk_field_layout id =
- {
- fl_id = id;
- fl_offset = -1;
- fl_field = null_field;
- }
- let mk_stand_alone_sig id =
- {
- sa_id = id;
- sa_signature = SVoid;
- }
- let mk_event id =
- {
- e_id = id;
- e_flags = [];
- e_name = empty;
- e_event_type = null_meta;
- }
- let null_event = mk_event (-1)
- let mk_event_map id =
- {
- em_id = id;
- em_parent = null_type_def;
- em_event_list = [];
- }
- let mk_event_ptr id =
- {
- ep_id = id;
- ep_event = null_event;
- }
- let mk_property id =
- {
- prop_id = id;
- prop_flags = [];
- prop_name = empty;
- prop_type = SVoid;
- }
- let null_property = mk_property (-1)
- let mk_property_map id =
- {
- pm_id = id;
- pm_parent = null_type_def;
- pm_property_list = [];
- }
- let mk_property_ptr id =
- {
- prp_id = id;
- prp_property = null_property;
- }
- let mk_method_semantics id =
- {
- ms_id = id;
- ms_semantic = [];
- ms_method = null_method;
- ms_association = null_meta;
- }
- let mk_method_impl id =
- {
- mi_id = id;
- mi_class = null_type_def;
- mi_method_body = null_meta;
- mi_method_declaration = null_meta;
- }
- let mk_module_ref id =
- {
- modr_id = id;
- modr_name = empty;
- }
- let null_module_ref = mk_module_ref (-1)
- let mk_type_spec id =
- {
- ts_id = id;
- ts_signature = SVoid;
- }
- let mk_enc_log id =
- {
- el_id = id;
- el_token = -1;
- el_func_code = -1;
- }
- let mk_impl_map id =
- {
- im_id = id;
- im_flags = null_impl_flags;
- im_forwarded = null_meta;
- im_import_name = empty;
- im_import_scope = null_module_ref;
- }
- let mk_enc_map id =
- {
- encm_id = id;
- encm_token = -1;
- }
- let mk_field_rva id =
- {
- fr_id = id;
- fr_rva = Int32.zero;
- fr_field = null_field;
- }
- let mk_assembly id =
- {
- a_id = id;
- a_hash_algo = HNone;
- a_major = -1;
- a_minor = -1;
- a_build = -1;
- a_rev = -1;
- a_flags = [];
- a_public_key = empty;
- a_name = empty;
- a_locale = empty;
- }
- let mk_assembly_processor id =
- {
- ap_id = id;
- ap_processor = -1;
- }
- let mk_assembly_os id =
- {
- aos_id = id;
- aos_platform_id = -1;
- aos_major_version = -1;
- aos_minor_version = -1;
- }
- let mk_assembly_ref id =
- {
- ar_id = id;
- ar_major = -1;
- ar_minor = -1;
- ar_build = -1;
- ar_rev = -1;
- ar_flags = [];
- ar_public_key = empty;
- ar_name = empty;
- ar_locale = empty;
- ar_hash_value = empty;
- }
- let null_assembly_ref = mk_assembly_ref (-1)
- let mk_assembly_ref_processor id =
- {
- arp_id = id;
- arp_processor = -1;
- arp_assembly_ref = null_assembly_ref;
- }
- let mk_assembly_ref_os id =
- {
- aros_id = id;
- aros_platform_id = -1;
- aros_major = -1;
- aros_minor = -1;
- aros_assembly_ref = null_assembly_ref;
- }
- let mk_file id =
- {
- file_id = id;
- file_flags = ContainsMetadata;
- file_name = empty;
- file_hash_value = empty;
- }
- let mk_exported_type id =
- {
- et_id = id;
- et_flags = null_type_def_flags;
- et_type_def_id = -1;
- et_type_name = empty;
- et_type_namespace = [];
- et_implementation = null_meta;
- }
- let mk_manifest_resource id =
- {
- mr_id = id;
- mr_offset = -1;
- mr_flags = RNone;
- mr_name = empty;
- mr_implementation = None;
- }
- let mk_nested_class id =
- {
- nc_id = id;
- nc_nested = null_type_def;
- nc_enclosing = null_type_def;
- }
- let mk_generic_param id =
- {
- gp_id = id;
- gp_number = -1;
- gp_flags = null_generic_flags;
- gp_owner = null_meta;
- gp_name = None;
- }
- let null_generic_param = mk_generic_param (-1)
- let mk_method_spec id =
- {
- mspec_id = id;
- mspec_method = null_meta;
- mspec_instantiation = SVoid;
- }
- let mk_generic_param_constraint id =
- {
- gc_id = id;
- gc_owner = null_generic_param;
- gc_constraint = null_meta;
- }
- let mk_meta tbl id = match tbl with
- | IModule -> Module (mk_module id)
- | ITypeRef -> TypeRef (mk_type_ref id)
- | ITypeDef -> TypeDef (mk_type_def id)
- | IFieldPtr -> FieldPtr (mk_field_ptr id)
- | IField -> Field (mk_field id)
- | IMethodPtr -> MethodPtr (mk_method_ptr id)
- | IMethod -> Method (mk_method id)
- | IParamPtr -> ParamPtr (mk_param_ptr id)
- | IParam -> Param (mk_param id)
- | IInterfaceImpl -> InterfaceImpl (mk_interface_impl id)
- | IMemberRef -> MemberRef (mk_member_ref id)
- | IConstant -> Constant (mk_constant id)
- | ICustomAttribute -> CustomAttribute (mk_custom_attribute id)
- | IFieldMarshal -> FieldMarshal(mk_field_marshal id)
- | IDeclSecurity -> DeclSecurity(mk_decl_security id)
- | IClassLayout -> ClassLayout(mk_class_layout id)
- | IFieldLayout -> FieldLayout(mk_field_layout id)
- | IStandAloneSig -> StandAloneSig(mk_stand_alone_sig id)
- | IEventMap -> EventMap(mk_event_map id)
- | IEventPtr -> EventPtr(mk_event_ptr id)
- | IEvent -> Event(mk_event id)
- | IPropertyMap -> PropertyMap(mk_property_map id)
- | IPropertyPtr -> PropertyPtr(mk_property_ptr id)
- | IProperty -> Property(mk_property id)
- | IMethodSemantics -> MethodSemantics(mk_method_semantics id)
- | IMethodImpl -> MethodImpl(mk_method_impl id)
- | IModuleRef -> ModuleRef(mk_module_ref id)
- | ITypeSpec -> TypeSpec(mk_type_spec id)
- | IImplMap -> ImplMap(mk_impl_map id)
- | IFieldRVA -> FieldRVA(mk_field_rva id)
- | IENCLog -> ENCLog(mk_enc_log id)
- | IENCMap -> ENCMap(mk_enc_map id)
- | IAssembly -> Assembly(mk_assembly id)
- | IAssemblyProcessor -> AssemblyProcessor(mk_assembly_processor id)
- | IAssemblyOS -> AssemblyOS(mk_assembly_os id)
- | IAssemblyRef -> AssemblyRef(mk_assembly_ref id)
- | IAssemblyRefProcessor -> AssemblyRefProcessor(mk_assembly_ref_processor id)
- | IAssemblyRefOS -> AssemblyRefOS(mk_assembly_ref_os id)
- | IFile -> File(mk_file id)
- | IExportedType -> ExportedType(mk_exported_type id)
- | IManifestResource -> ManifestResource(mk_manifest_resource id)
- | INestedClass -> NestedClass(mk_nested_class id)
- | IGenericParam -> GenericParam(mk_generic_param id)
- | IMethodSpec -> MethodSpec(mk_method_spec id)
- | IGenericParamConstraint -> GenericParamConstraint(mk_generic_param_constraint id)
- | i -> UnknownMeta (int_of_table i)
- let get_table ctx idx rid =
- let cur = ctx.tables.(int_of_table idx) in
- DynArray.get cur (rid-1)
- (* special coded types *)
- let max_clr_meta_idx = 76
- let coded_description = Array.init (max_clr_meta_idx - 63) (fun i ->
- let i = 64 + i in
- match table_of_int i with
- | ITypeDefOrRef ->
- Array.of_list [ITypeDef;ITypeRef;ITypeSpec], 2
- | IHasConstant ->
- Array.of_list [IField;IParam;IProperty], 2
- | IHasCustomAttribute ->
- Array.of_list
- [IMethod;IField;ITypeRef;ITypeDef;IParam;IInterfaceImpl;IMemberRef;
- IModule;IDeclSecurity;IProperty;IEvent;IStandAloneSig;IModuleRef;
- ITypeSpec;IAssembly;IAssemblyRef;IFile;IExportedType;IManifestResource;
- IGenericParam;IGenericParamConstraint;IMethodSpec], 5
- | IHasFieldMarshal ->
- Array.of_list [IField;IParam], 1
- | IHasDeclSecurity ->
- Array.of_list [ITypeDef;IMethod;IAssembly], 2
- | IMemberRefParent ->
- Array.of_list [ITypeDef;ITypeRef;IModuleRef;IMethod;ITypeSpec], 3
- | IHasSemantics ->
- Array.of_list [IEvent;IProperty], 1
- | IMethodDefOrRef ->
- Array.of_list [IMethod;IMemberRef], 1
- | IMemberForwarded ->
- Array.of_list [IField;IMethod], 1
- | IImplementation ->
- Array.of_list [IFile;IAssemblyRef;IExportedType], 2
- | ICustomAttributeType ->
- Array.of_list [ITypeRef(* unused ? *);ITypeDef (* unused ? *);IMethod;IMemberRef(*;IString FIXME *)], 3
- | IResolutionScope ->
- Array.of_list [IModule;IModuleRef;IAssemblyRef;ITypeRef], 2
- | ITypeOrMethodDef ->
- Array.of_list [ITypeDef;IMethod], 1
- | _ ->
- print_endline ("Unknown coded index: " ^ string_of_int i);
- assert false)
- let set_coded_sizes ctx rows =
- let check i tbls max =
- if List.exists (fun t ->
- let _, nrows = rows.(int_of_table t) in
- nrows >= max
- ) tbls then
- ctx.table_sizes.(i) <- sread_i32
- in
- for i = 64 to (max_clr_meta_idx) do
- let tbls, size = coded_description.(i - 64) in
- let max = 1 lsl (16 - size) in
- check i (Array.to_list tbls) max
- done
- let sread_from_table_opt ctx in_blob tbl s pos =
- let i = int_of_table tbl in
- let sread = if in_blob then
- read_compressed_i32
- else
- ctx.table_sizes.(i)
- in
- let pos, rid = sread s pos in
- if i >= 64 then begin
- let tbls,size = coded_description.(i-64) in
- let mask = (1 lsl size) - 1 in
- let mask = if mask = 0 then 1 else mask in
- let tidx = rid land mask in
- let real_rid = rid lsr size in
- let real_tbl = tbls.(tidx) in
- (* printf "rid 0x%x - table idx 0x%x - real_rid 0x%x\n\n" rid tidx real_rid; *)
- if real_rid = 0 then
- pos, None
- else
- pos, Some (get_table ctx real_tbl real_rid)
- end else if rid = 0 then
- pos, None
- else
- pos, Some (get_table ctx tbl rid)
- let sread_from_table ctx in_blob tbl s pos =
- let pos, opt = sread_from_table_opt ctx in_blob tbl s pos in
- pos, Option.get opt
- (* ******* SIGNATURE READING ********* *)
- let read_inline_str s pos =
- let pos, len = read_compressed_i32 s pos in
- let ret = String.sub s pos len in
- pos+len,ret
- let rec read_ilsig ctx s pos =
- let i = sget s pos in
- (* printf "0x%x\n" i; *)
- let pos = pos + 1 in
- match i with
- | 0x1 -> pos, SVoid (* 0x1 *)
- | 0x2 -> pos, SBool (* 0x2 *)
- | 0x3 -> pos, SChar (* 0x3 *)
- | 0x4 -> pos, SInt8 (* 0x4 *)
- | 0x5 -> pos, SUInt8 (* 0x5 *)
- | 0x6 -> pos, SInt16 (* 0x6 *)
- | 0x7 -> pos, SUInt16 (* 0x7 *)
- | 0x8 -> pos, SInt32 (* 0x8 *)
- | 0x9 -> pos, SUInt32 (* 0x9 *)
- | 0xA -> pos, SInt64 (* 0xA *)
- | 0xB -> pos, SUInt64 (* 0xB *)
- | 0xC -> pos, SFloat32 (* 0xC *)
- | 0xD -> pos, SFloat64 (* 0xD *)
- | 0xE -> pos, SString (* 0xE *)
- | 0xF ->
- let pos, s = read_ilsig ctx s pos in
- pos, SPointer s
- | 0x10 ->
- let pos, s = read_ilsig ctx s pos in
- pos, SManagedPointer s
- | 0x11 ->
- let pos, vt = sread_from_table ctx true ITypeDefOrRef s pos in
- pos, SValueType vt
- | 0x12 ->
- let pos, c = sread_from_table ctx true ITypeDefOrRef s pos in
- pos, SClass c
- | 0x13 ->
- let n = sget s pos in
- pos + 1, STypeParam n
- | 0x14 ->
- let pos, ssig = read_ilsig ctx s pos in
- let pos, rank = read_compressed_i32 s pos in
- let pos, numsizes = read_compressed_i32 s pos in
- let pos = ref pos in
- let sizearray = Array.init numsizes (fun _ ->
- let p, size = read_compressed_i32 s !pos in
- pos := p;
- size
- ) in
- let pos, bounds = read_compressed_i32 s !pos in
- let pos = ref pos in
- let boundsarray = Array.init bounds (fun _ ->
- let p, b = read_compressed_i32 s !pos in
- pos := p;
- let signed = b land 0x1 = 0x1 in
- let b = b lsr 1 in
- if signed then -b else b
- ) in
- let ret = Array.init rank (fun i ->
- (if i >= bounds then None else Some boundsarray.(i))
- , (if i >= numsizes then None else Some sizearray.(i))
- ) in
- !pos, SArray(ssig, ret)
- | 0x15 ->
- (* let pos, c = sread_from_table ctx ITypeDefOrRef s pos in *)
- let pos, ssig = read_ilsig ctx s pos in
- let pos, ntypes = read_compressed_i32 s pos in
- let rec loop acc pos n =
- if n > ntypes then
- pos, List.rev acc
- else
- let pos, ssig = read_ilsig ctx s pos in
- loop (ssig :: acc) pos (n+1)
- in
- let pos, args = loop [] pos 1 in
- pos, SGenericInst (ssig, args)
- | 0x16 -> pos, STypedReference (* 0x16 *)
- | 0x18 -> pos, SIntPtr (* 0x18 *)
- | 0x19 -> pos, SUIntPtr (* 0x19 *)
- | 0x1B ->
- let pos, conv = read_compressed_i32 s pos in
- let callconv = callconv_of_int conv in
- let pos, ntypes = read_compressed_i32 s pos in
- let pos, ret = read_ilsig ctx s pos in
- let rec loop acc pos n =
- if n >= ntypes then
- pos, List.rev acc
- else
- let pos, ssig = read_ilsig ctx s pos in
- loop (ssig :: acc) pos (n+1)
- in
- let pos, args = loop [] pos 1 in
- pos, SFunPtr (callconv, ret, args)
- | 0x1C -> pos, SObject (* 0x1C *)
- | 0x1D ->
- let pos, ssig = read_ilsig ctx s pos in
- pos, SVector ssig
- | 0x1E ->
- let pos, conv = read_compressed_i32 s pos in
- pos, SMethodTypeParam conv
- | 0x1F ->
- let pos, tdef = sread_from_table ctx true ITypeDefOrRef s pos in
- let pos, ilsig = read_ilsig ctx s pos in
- pos, SReqModifier (tdef, ilsig)
- | 0x20 ->
- let pos, tdef = sread_from_table ctx true ITypeDefOrRef s pos in
- let pos, ilsig = read_ilsig ctx s pos in
- pos, SOptModifier (tdef, ilsig)
- | 0x41 -> pos, SSentinel (* 0x41 *)
- | 0x45 ->
- let pos, ssig = read_ilsig ctx s pos in
- pos,SPinned ssig (* 0x45 *)
- (* special undocumented constants *)
- | 0x50 -> pos, SType
- | 0x51 -> pos, SBoxed
- | 0x55 ->
- let pos, vt = read_inline_str s pos in
- pos, SEnum vt
- | _ ->
- Printf.printf "unknown ilsig 0x%x\n\n" i;
- assert false
- let rec read_variantsig ctx s pos =
- let pos, b = sread_ui8 s pos in
- match b with
- | 0x00 -> pos, VT_EMPTY (* 0x00 *)
- | 0x01 -> pos, VT_NULL (* 0x01 *)
- | 0x02 -> pos, VT_I2 (* 0x02 *)
- | 0x03 -> pos, VT_I4 (* 0x03 *)
- | 0x04 -> pos, VT_R4 (* 0x04 *)
- | 0x05 -> pos, VT_R8 (* 0x05 *)
- | 0x06 -> pos, VT_CY (* 0x06 *)
- | 0x07 -> pos, VT_DATE (* 0x07 *)
- | 0x08 -> pos, VT_BSTR (* 0x08 *)
- | 0x09 -> pos, VT_DISPATCH (* 0x09 *)
- | 0x0A -> pos, VT_ERROR (* 0x0A *)
- | 0x0B -> pos, VT_BOOL (* 0x0B *)
- | 0x0C -> pos, VT_VARIANT (* 0x0C *)
- | 0x0D -> pos, VT_UNKNOWN (* 0x0D *)
- | 0x0E -> pos, VT_DECIMAL (* 0x0E *)
- | 0x10 -> pos, VT_I1 (* 0x10 *)
- | 0x11 -> pos, VT_UI1 (* 0x11 *)
- | 0x12 -> pos, VT_UI2 (* 0x12 *)
- | 0x13 -> pos, VT_UI4 (* 0x13 *)
- | 0x14 -> pos, VT_I8 (* 0x14 *)
- | 0x15 -> pos, VT_UI8 (* 0x15 *)
- | 0x16 -> pos, VT_INT (* 0x16 *)
- | 0x17 -> pos, VT_UINT (* 0x17 *)
- | 0x18 -> pos, VT_VOID (* 0x18 *)
- | 0x19 -> pos, VT_HRESULT (* 0x19 *)
- | 0x1A -> pos, VT_PTR (* 0x1A *)
- | 0x1B -> pos, VT_SAFEARRAY (* 0x1B *)
- | 0x1C -> pos, VT_CARRAY (* 0x1C *)
- | 0x1D -> pos, VT_USERDEFINED (* 0x1D *)
- | 0x1E -> pos, VT_LPSTR (* 0x1E *)
- | 0x1F -> pos, VT_LPWSTR (* 0x1F *)
- | 0x24 -> pos, VT_RECORD (* 0x24 *)
- | 0x40 -> pos, VT_FILETIME (* 0x40 *)
- | 0x41 -> pos, VT_BLOB (* 0x41 *)
- | 0x42 -> pos, VT_STREAM (* 0x42 *)
- | 0x43 -> pos, VT_STORAGE (* 0x43 *)
- | 0x44 -> pos, VT_STREAMED_OBJECT (* 0x44 *)
- | 0x45 -> pos, VT_STORED_OBJECT (* 0x45 *)
- | 0x46 -> pos, VT_BLOB_OBJECT (* 0x46 *)
- | 0x47 -> pos, VT_CF (* 0x47 *)
- | 0x48 -> pos, VT_CLSID (* 0x48 *)
- | _ -> assert false
- let rec read_nativesig ctx s pos : int * nativesig =
- let pos, b = sread_ui8 s pos in
- match b with
- | 0x01 -> pos, NVoid (* 0x01 *)
- | 0x02 -> pos, NBool (* 0x02 *)
- | 0x03 -> pos, NInt8 (* 0x03 *)
- | 0x4 -> pos, NUInt8 (* 0x4 *)
- | 0x5 -> pos, NInt16 (* 0x5 *)
- | 0x6 -> pos, NUInt16 (* 0x6 *)
- | 0x7 -> pos, NInt32 (* 0x7 *)
- | 0x8 -> pos, NUInt32 (* 0x8 *)
- | 0x9 -> pos, NInt64 (* 0x9 *)
- | 0xA -> pos, NUInt64 (* 0xA *)
- | 0xB -> pos, NFloat32 (* 0xB *)
- | 0xC -> pos, NFloat64 (* 0xC *)
- | 0xD -> pos, NSysChar (* 0xD *)
- | 0xE -> pos, NVariant (* 0xE *)
- | 0xF -> pos, NCurrency (* 0xF *)
- | 0x10 -> pos, NPointer (* 0x10 *)
- | 0x11 -> pos, NDecimal (* 0x11 *)
- | 0x12 -> pos, NDate (* 0x12 *)
- | 0x13 -> pos, NBStr (* 0x13 *)
- | 0x14 -> pos, NLPStr (* 0x14 *)
- | 0x15 -> pos, NLPWStr (* 0x15 *)
- | 0x16 -> pos, NLPTStr (* 0x16 *)
- | 0x17 ->
- let pos, size = read_compressed_i32 s pos in
- pos, NFixedString size
- | 0x18 -> pos, NObjectRef (* 0x18 *)
- | 0x19 -> pos, NUnknown (* 0x19 *)
- | 0x1A -> pos, NDispatch (* 0x1A *)
- | 0x1B -> pos, NStruct (* 0x1B *)
- | 0x1C -> pos, NInterface (* 0x1C *)
- | 0x1D ->
- let pos, v = read_variantsig ctx s pos in
- pos, NSafeArray v
- | 0x1E ->
- let pos, size = read_compressed_i32 s pos in
- let pos, t = read_variantsig ctx s pos in
- pos, NFixedArray (size,t)
- | 0x1F -> pos, NIntPointer (* 0x1F *)
- | 0x20 -> pos, NUIntPointer (* 0x20 *)
- | 0x21 -> pos, NNestedStruct (* 0x21 *)
- | 0x22 -> pos, NByValStr (* 0x22 *)
- | 0x23 -> pos, NAnsiBStr (* 0x23 *)
- | 0x24 -> pos, NTBStr (* 0x24 *)
- | 0x25 -> pos, NVariantBool (* 0x25 *)
- | 0x26 -> pos, NFunctionPtr (* 0x26 *)
- | 0x28 -> pos, NAsAny (* 0x28 *)
- | 0x2A ->
- let pos, elt = read_nativesig ctx s pos in
- let pos, paramidx = read_compressed_i32 s pos in
- let pos, size = read_compressed_i32 s pos in
- let pos, param_mult = read_compressed_i32 s pos in
- pos, NArray(elt,paramidx,size,param_mult)
- | 0x2B -> pos, NLPStruct (* 0x2B *)
- | 0x2C ->
- let pos, guid_val = read_inline_str s pos in
- let pos, unmanaged = read_inline_str s pos in
- (* FIXME: read TypeRef *)
- pos, NCustomMarshaler (guid_val,unmanaged)
- | 0x2D -> pos, NError (* 0x2D *)
- | i -> pos, NCustom i
- let read_blob_idx ctx s pos =
- let metapos,i = if ctx.blob_offset = 2 then
- sread_ui16 s pos
- else
- sread_i32 s pos
- in
- metapos, i
- let read_nativesig_idx ctx s pos =
- let s = ctx.meta_stream in
- let metapos,i = if ctx.blob_offset = 2 then
- sread_ui16 s pos
- else
- sread_i32 s pos
- in
- let s = ctx.blob_stream in
- let _, ret = read_nativesig ctx s i in
- metapos, ret
- let read_method_ilsig_idx ctx pos =
- let s = ctx.meta_stream in
- let metapos,i = if ctx.blob_offset = 2 then
- sread_ui16 s pos
- else
- sread_i32 s pos
- in
- let s = ctx.blob_stream in
- let pos, len = read_compressed_i32 s i in
- (* for x = 0 to len do *)
- (* printf "%x " (sget s (i+x)) *)
- (* done; *)
- let endpos = pos + len in
- (* printf "\n"; *)
- let pos, callconv = read_callconv ctx s pos in
- let pos, ntypes = read_compressed_i32 s pos in
- let pos, ret = read_ilsig ctx s pos in
- let rec loop acc pos n =
- if n > ntypes || pos >= endpos then
- pos, List.rev acc
- else
- let pos, ssig = read_ilsig ctx s pos in
- loop (ssig :: acc) pos (n+1)
- in
- let pos, args = loop [] pos 1 in
- metapos, SFunPtr (callconv, ret, args)
- let read_ilsig_idx ctx pos =
- let s = ctx.meta_stream in
- let metapos,i = if ctx.blob_offset = 2 then
- sread_ui16 s pos
- else
- sread_i32 s pos
- in
- let s = ctx.blob_stream in
- let i, _ = read_compressed_i32 s i in
- let _, ilsig = read_ilsig ctx s i in
- metapos, ilsig
- let read_field_ilsig_idx ?(force_field=true) ctx pos =
- let s = ctx.meta_stream in
- let metapos,i = if ctx.blob_offset = 2 then
- sread_ui16 s pos
- else
- sread_i32 s pos
- in
- let s = ctx.blob_stream in
- let i, _ = read_compressed_i32 s i in
- if sget s i <> 0x6 then
- if force_field then
- error ("Invalid field signature: " ^ string_of_int (sget s i))
- else
- read_method_ilsig_idx ctx pos
- else
- let _, ilsig = read_ilsig ctx s (i+1) in
- metapos, ilsig
- let get_underlying_enum_type ctx name =
- (* first try to get a typedef *)
- let ns, name = match List.rev (String.nsplit name ".") with
- | name :: ns -> List.rev ns, name
- | _ -> assert false
- in
- try
- let tdefs = ctx.tables.(int_of_table ITypeDef) in
- let len = DynArray.length tdefs in
- let rec loop_find idx =
- if idx >= len then
- raise Not_found
- else
- let tdef = match DynArray.get tdefs idx with | TypeDef td -> td | _ -> assert false in
- if tdef.td_name = name && tdef.td_namespace = ns then
- tdef
- else
- loop_find (idx+1)
- in
- let tdef = loop_find 1 in
- (* now find the first static field associated with it *)
- try
- let nonstatic = List.find (fun f ->
- not (List.mem CStatic f.f_flags.ff_contract)
- ) tdef.td_field_list in
- nonstatic.f_signature
- with | Not_found -> assert false (* should never happen! *)
- with | Not_found ->
- (* FIXME: in order to correctly handle SEnum, we need to look it up *)
- (* from either this assembly or from any other assembly that we reference *)
- (* this is tricky - specially since this reader does not intend to handle file system *)
- (* operations by itself. For now, if an enum is referenced from another module, *)
- (* we won't handle it. The `cache` structure is laid out to deal with these problems *)
- (* but isn't implemented yet *)
- raise Exit
- let read_custom_attr ctx attr_type s pos =
- let pos, prolog = sread_ui16 s pos in
- if prolog <> 0x0001 then error (sprintf "Error reading custom attribute: Expected prolog 0x0001 ; got 0x%x" prolog);
- let isig = match attr_type with
- | Method m -> m.m_signature
- | MemberRef mr -> mr.memr_signature
- | _ -> assert false
- in
- let args = match follow isig with
- | SFunPtr (_,ret,args) -> args
- | _ -> assert false
- in
- let rec read_instance ilsig pos =
- (* print_endline (IlMetaDebug.ilsig_s ilsig); *)
- match follow ilsig with
- | SBool | SChar | SInt8 | SUInt8 | SInt16 | SUInt16
- | SInt32 | SUInt32 | SInt64 | SUInt64 | SFloat32 | SFloat64 | SString ->
- let pos, cons = read_constant ctx (sig_to_const ilsig) s pos in
- pos, InstConstant (cons)
- | SClass c when is_type (["System"],"Type") c ->
- if (sget s pos) == 0xff then
- pos+1, InstConstant INull
- else
- let pos, len = read_compressed_i32 s pos in
- pos+len, InstType (String.sub s pos len)
- | SType ->
- let pos, len = read_compressed_i32 s pos in
- pos+len, InstType (String.sub s pos len)
- | SObject | SBoxed -> (* boxed *)
- let pos = if sget s pos = 0x51 then pos+1 else pos in
- let pos, ilsig = read_ilsig ctx s pos in
- let pos, ret = read_instance ilsig pos in
- pos, InstBoxed( ret )
- (* (match follow ilsig with *)
- (* | SEnum e -> *)
- (* let ilsig = get_underlying_enum_type ctx e; *)
- (* let pos,e = if is_boxed then sread_i32 s pos else read_compressed_i32 s pos in *)
- (* pos, InstBoxed(InstEnum e) *)
- (* | _ -> *)
- (* let pos, boxed = read_constant ctx (sig_to_const ilsig) s pos in *)
- (* pos, InstBoxed (InstConstant boxed)) *)
- | SEnum e ->
- let ilsig = get_underlying_enum_type ctx e in
- read_instance ilsig pos
- | SValueType _ -> (* enum *)
- let pos, e = sread_i32 s pos in
- pos, InstEnum e
- | _ -> assert false
- in
- let rec read_fixed acc args pos = match args with
- | [] ->
- pos, List.rev acc
- | SVector isig :: args ->
- (* print_endline "vec"; *)
- let pos, nelem = sread_real_i32 s pos in
- let pos, ret = if nelem = -1l then
- pos, InstConstant INull
- else
- let nelem = Int32.to_int nelem in
- let rec loop acc pos n =
- if n = nelem then
- pos, InstArray (List.rev acc)
- else
- let pos, inst = read_instance isig pos in
- loop (inst :: acc) pos (n+1)
- in
- loop [] pos 0
- in
- read_fixed (ret :: acc) args pos
- | isig :: args ->
- let pos, i = read_instance isig pos in
- read_fixed (i :: acc) args pos
- in
- (* let tpos = pos in *)
- let pos, fixed = read_fixed [] args pos in
- (* printf "fixed %d : " (List.length args); *)
- (* for x = tpos to pos do *)
- (* printf "%x " (sget s x) *)
- (* done; *)
- (* printf "\n"; *)
- (* let len = String.length s - pos - 1 in *)
- (* let len = if len > 10 then 10 else len in *)
- (* for x = 0 to len do *)
- (* printf "%x " (sget s (pos + x)) *)
- (* done; *)
- (* printf "\n"; *)
- let pos, nnamed = read_compressed_i32 s pos in
- let pos = if nnamed > 0 then pos+1 else pos in
- (* FIXME: this is a hack / quick fix around #3485 . We need to actually read named arguments *)
- (* let rec read_named acc pos n = *)
- (* if n = nnamed then *)
- (* pos, List.rev acc *)
- (* else *)
- (* let pos, forp = sread_ui8 s pos in *)
- (* let is_prop = if forp = 0x53 then *)
- (* false *)
- (* else if forp = 0x54 then *)
- (* true *)
- (* else *)
- (* error (sprintf "named custom attribute error: expected 0x53 or 0x54 - got 0x%x" forp) *)
- (* in *)
- (* let pos, t = read_ilsig ctx s pos in *)
- (* let pos, len = read_compressed_i32 s pos in *)
- (* let name = String.sub s pos len in *)
- (* let pos = pos+len in *)
- (* let pos, inst = read_instance t pos in *)
- (* read_named ( (is_prop, name, inst) :: acc ) pos (n+1) *)
- (* in *)
- (* let pos, named = read_named [] pos 0 in *)
- pos, (fixed, [])
- (* pos, (fixed, named) *)
- let read_custom_attr_idx ctx ca attr_type pos =
- let s = ctx.meta_stream in
- let metapos,i = if ctx.blob_offset = 2 then
- sread_ui16 s pos
- else
- sread_i32 s pos
- in
- if i = 0 then
- metapos
- else
- let s = ctx.blob_stream in
- let i, _ = read_compressed_i32 s i in
- ctx.delays <- (fun () ->
- try
- let _, attr = read_custom_attr ctx attr_type s i in
- ca.ca_value <- Some attr
- with | Exit ->
- ()
- ) :: ctx.delays;
- metapos
- let read_next_index ctx offset table last pos =
- if last then
- DynArray.length ctx.tables.(int_of_table table) + 1
- else
- let s = ctx.meta_stream in
- let _, idx = ctx.table_sizes.(int_of_table table) s (pos+offset) in
- idx
- let get_rev_list ctx table ptr_table begin_idx end_idx =
- (* first check if index exists on pointer table *)
- let ptr_table_t = ctx.tables.(int_of_table ptr_table) in
- (* printf "table %d begin %d end %d\n" (int_of_table table) begin_idx end_idx; *)
- match ctx.compressed, DynArray.length ptr_table_t with
- | true, _ | _, 0 ->
- (* use direct index *)
- let rec loop idx acc =
- if idx >= end_idx then
- acc
- else
- loop (idx+1) (get_table ctx table idx :: acc)
- in
- loop begin_idx []
- | _ ->
- (* use indirect index *)
- let rec loop idx acc =
- if idx > end_idx then
- acc
- else
- loop (idx+1) (get_table ctx ptr_table idx :: acc)
- in
- let ret = loop begin_idx [] in
- List.map (fun meta ->
- let p = meta_root_ptr meta in
- get_table ctx table p.ptr_to.root_id
- ) ret
- let read_list ctx table ptr_table begin_idx offset last pos =
- let end_idx = read_next_index ctx offset table last pos in
- get_rev_list ctx table ptr_table begin_idx end_idx
- let parse_ns id = match String.nsplit id "." with
- | [""] -> []
- | ns -> ns
- let get_meta_pointer = function
- | Module r -> IModule, r.md_id
- | TypeRef r -> ITypeRef, r.tr_id
- | TypeDef r -> ITypeDef, r.td_id
- | FieldPtr r -> IFieldPtr, r.fp_id
- | Field r -> IField, r.f_id
- | MethodPtr r -> IMethodPtr, r.mp_id
- | Method r -> IMethod, r.m_id
- | ParamPtr r -> IParamPtr, r.pp_id
- | Param r -> IParam, r.p_id
- | InterfaceImpl r -> IInterfaceImpl, r.ii_id
- | MemberRef r -> IMemberRef, r.memr_id
- | Constant r -> IConstant, r.c_id
- | CustomAttribute r -> ICustomAttribute, r.ca_id
- | FieldMarshal r -> IFieldMarshal, r.fm_id
- | DeclSecurity r -> IDeclSecurity, r.ds_id
- | ClassLayout r -> IClassLayout, r.cl_id
- | FieldLayout r -> IFieldLayout, r.fl_id
- | StandAloneSig r -> IStandAloneSig, r.sa_id
- | EventMap r -> IEventMap, r.em_id
- | EventPtr r -> IEventPtr, r.ep_id
- | Event r -> IEvent, r.e_id
- | PropertyMap r -> IPropertyMap, r.pm_id
- | PropertyPtr r -> IPropertyPtr, r.prp_id
- | Property r -> IProperty, r.prop_id
- | MethodSemantics r -> IMethodSemantics, r.ms_id
- | MethodImpl r -> IMethodImpl, r.mi_id
- | ModuleRef r -> IModuleRef, r.modr_id
- | TypeSpec r -> ITypeSpec, r.ts_id
- | ImplMap r -> IImplMap, r.im_id
- | FieldRVA r -> IFieldRVA, r.fr_id
- | ENCLog r -> IENCLog, r.el_id
- | ENCMap r -> IENCMap, r.encm_id
- | Assembly r -> IAssembly, r.a_id
- | AssemblyProcessor r -> IAssemblyProcessor, r.ap_id
- | AssemblyOS r -> IAssemblyOS, r.aos_id
- | AssemblyRef r -> IAssemblyRef, r.ar_id
- | AssemblyRefProcessor r -> IAssemblyRefProcessor, r.arp_id
- | AssemblyRefOS r -> IAssemblyRefOS, r.aros_id
- | File r -> IFile, r.file_id
- | ExportedType r -> IExportedType, r.et_id
- | ManifestResource r -> IManifestResource, r.mr_id
- | NestedClass r -> INestedClass, r.nc_id
- | GenericParam r -> IGenericParam, r.gp_id
- | MethodSpec r -> IMethodSpec, r.mspec_id
- | GenericParamConstraint r -> IGenericParamConstraint, r.gc_id
- | _ -> assert false
- let add_relation ctx key v =
- let ptr = get_meta_pointer key in
- Hashtbl.add ctx.relations ptr v
- let read_table_at ctx tbl n last pos =
- (* print_endline ("rr " ^ string_of_int (n+1)); *)
- let s = ctx.meta_stream in
- match get_table ctx tbl (n+1 (* indices start at 1 *)) with
- | Module m ->
- let pos, gen = sread_ui16 s pos in
- let pos, name = read_sstring_idx ctx pos in
- let pos, vid = read_sguid_idx ctx pos in
- let pos, encid = read_sguid_idx ctx pos in
- let pos, encbase_id = read_sguid_idx ctx pos in
- m.md_generation <- gen;
- m.md_name <- name;
- m.md_vid <- vid;
- m.md_encid <- encid;
- m.md_encbase_id <- encbase_id;
- pos, Module m
- | TypeRef tr ->
- let pos, scope = sread_from_table ctx false IResolutionScope s pos in
- let pos, name = read_sstring_idx ctx pos in
- let pos, ns = read_sstring_idx ctx pos in
- tr.tr_resolution_scope <- scope;
- tr.tr_name <- name;
- tr.tr_namespace <- parse_ns ns;
- (* print_endline name; *)
- (* print_endline ns; *)
- pos, TypeRef tr
- | TypeDef td ->
- let startpos = pos in
- let pos, flags = sread_i32 s pos in
- let pos, name = read_sstring_idx ctx pos in
- let pos, ns = read_sstring_idx ctx pos in
- let ns = parse_ns ns in
- let pos, extends = sread_from_table_opt ctx false ITypeDefOrRef s pos in
- let field_offset = pos - startpos in
- let pos, flist_begin = ctx.table_sizes.(int_of_table IField) s pos in
- let method_offset = pos - startpos in
- let pos, mlist_begin = ctx.table_sizes.(int_of_table IMethod) s pos in
- td.td_flags <- type_def_flags_of_int flags;
- td.td_name <- name;
- td.td_namespace <- ns;
- td.td_extends <- extends;
- td.td_field_list <- List.rev_map get_field (read_list ctx IField IFieldPtr flist_begin field_offset last pos);
- td.td_method_list <- List.rev_map get_method (read_list ctx IMethod IMethodPtr mlist_begin method_offset last pos);
- List.iter (fun m -> m.m_declaring <- Some td) td.td_method_list;
- let path = get_path (TypeDef td) in
- Hashtbl.add ctx.typedefs path td;
- (* print_endline "Type Def!"; *)
- (* print_endline name; *)
- (* print_endline ns; *)
- pos, TypeDef td
- | FieldPtr fp ->
- let pos, field = sread_from_table ctx false IField s pos in
- let field = get_field field in
- fp.fp_field <- field;
- pos, FieldPtr fp
- | Field f ->
- let pos, flags = sread_ui16 s pos in
- let pos, name = read_sstring_idx ctx pos in
- (* print_endline ("FIELD NAME " ^ name); *)
- let pos, ilsig = read_field_ilsig_idx ctx pos in
- (* print_endline (ilsig_s ilsig); *)
- f.f_flags <- field_flags_of_int flags;
- f.f_name <- name;
- f.f_signature <- ilsig;
- pos, Field f
- | MethodPtr mp ->
- let pos, m = sread_from_table ctx false IMethod s pos in
- let m = get_method m in
- mp.mp_method <- m;
- pos, MethodPtr mp
- | Method m ->
- let startpos = pos in
- let pos, rva = sread_i32 s pos in
- let pos, iflags = sread_ui16 s pos in
- let pos, flags = sread_ui16 s pos in
- let pos, name = read_sstring_idx ctx pos in
- let pos, ilsig = read_method_ilsig_idx ctx pos in
- let offset = pos - startpos in
- let pos, paramlist = ctx.table_sizes.(int_of_table IParam) s pos in
- m.m_rva <- Int32.of_int rva;
- m.m_flags <- method_flags_of_int iflags flags;
- m.m_name <- name;
- m.m_signature <- ilsig;
- m.m_param_list <- List.rev_map get_param (read_list ctx IParam IParamPtr paramlist offset last pos);
- pos, Method m
- | ParamPtr pp ->
- let pos, p = sread_from_table ctx false IParam s pos in
- let p = get_param p in
- pp.pp_param <- p;
- pos, ParamPtr pp
- | Param p ->
- let pos, flags = sread_ui16 s pos in
- let pos, sequence = sread_ui16 s pos in
- let pos, name = read_sstring_idx ctx pos in
- p.p_flags <- param_flags_of_int flags;
- p.p_sequence <- sequence;
- p.p_name <- name;
- pos, Param p
- | InterfaceImpl ii ->
- let pos, cls = sread_from_table ctx false ITypeDef s pos in
- add_relation ctx cls (InterfaceImpl ii);
- let cls = get_type_def cls in
- let pos, interface = sread_from_table ctx false ITypeDefOrRef s pos in
- ii.ii_class <- cls;
- ii.ii_interface <- interface;
- pos, InterfaceImpl ii
- | MemberRef mr ->
- let pos, cls = sread_from_table ctx false IMemberRefParent s pos in
- let pos, name = read_sstring_idx ctx pos in
- (* print_endline name; *)
- (* let pos, signature = read_ilsig_idx ctx pos in *)
- let pos, signature = read_field_ilsig_idx ~force_field:false ctx pos in
- (* print_endline (ilsig_s signature); *)
- mr.memr_class <- cls;
- mr.memr_name <- name;
- mr.memr_signature <- signature;
- add_relation ctx cls (MemberRef mr);
- pos, MemberRef mr
- | Constant c ->
- let pos, ctype = read_constant_type ctx s pos in
- let pos = pos+1 in
- let pos, parent = sread_from_table ctx false IHasConstant s pos in
- let pos, blobpos = if ctx.blob_offset = 2 then
- sread_ui16 s pos
- else
- sread_i32 s pos
- in
- let blob = ctx.blob_stream in
- let blobpos, _ = read_compressed_i32 blob blobpos in
- let _, value = read_constant ctx ctype blob blobpos in
- c.c_type <- ctype;
- c.c_parent <- parent;
- c.c_value <- value;
- add_relation ctx parent (Constant c);
- pos, Constant c
- | CustomAttribute ca ->
- let pos, parent = sread_from_table ctx false IHasCustomAttribute s pos in
- let pos, t = sread_from_table ctx false ICustomAttributeType s pos in
- let pos = read_custom_attr_idx ctx ca t pos in
- ca.ca_parent <- parent;
- ca.ca_type <- t;
- ca.ca_value <- None; (* this will be delayed by read_custom_attr_idx *)
- add_relation ctx parent (CustomAttribute ca);
- pos, CustomAttribute ca
- | FieldMarshal fm ->
- let pos, parent = sread_from_table ctx false IHasFieldMarshal s pos in
- let pos, nativesig = read_nativesig_idx ctx s pos in
- fm.fm_parent <- parent;
- fm.fm_native_type <- nativesig;
- add_relation ctx parent (FieldMarshal fm);
- pos, FieldMarshal fm
- | DeclSecurity ds ->
- let pos, action = sread_ui16 s pos in
- let action = action_security_of_int action in
- let pos, parent = sread_from_table ctx false IHasDeclSecurity s pos in
- let pos, permission_set = read_sblob_idx ctx pos in
- ds.ds_action <- action;
- ds.ds_parent <- parent;
- ds.ds_permission_set <- permission_set;
- add_relation ctx parent (DeclSecurity ds);
- pos, DeclSecurity ds
- | ClassLayout cl ->
- let pos, psize = sread_ui16 s pos in
- let pos, csize = sread_i32 s pos in
- let pos, parent = sread_from_table ctx false ITypeDef s pos in
- add_relation ctx parent (ClassLayout cl);
- let parent = get_type_def parent in
- cl.cl_packing_size <- psize;
- cl.cl_class_size <- csize;
- cl.cl_parent <- parent;
- pos, ClassLayout cl
- | FieldLayout fl ->
- let pos, offset = sread_i32 s pos in
- let pos, field = sread_from_table ctx false IField s pos in
- fl.fl_offset <- offset;
- fl.fl_field <- get_field field;
- add_relation ctx field (FieldLayout fl);
- pos, FieldLayout fl
- | StandAloneSig sa ->
- let pos, ilsig = read_field_ilsig_idx ~force_field:false ctx pos in
- (* print_endline (ilsig_s ilsig); *)
- sa.sa_signature <- ilsig;
- pos, StandAloneSig sa
- | EventMap em ->
- let startpos = pos in
- let pos, parent = sread_from_table ctx false ITypeDef s pos in
- let offset = pos - startpos in
- let pos, event_list = ctx.table_sizes.(int_of_table IEvent) s pos in
- em.em_parent <- get_type_def parent;
- em.em_event_list <- List.rev_map get_event (read_list ctx IEvent IEventPtr event_list offset last pos);
- add_relation ctx parent (EventMap em);
- pos, EventMap em
- | EventPtr ep ->
- let pos, event = sread_from_table ctx false IEvent s pos in
- ep.ep_event <- get_event event;
- pos, EventPtr ep
- | Event e ->
- let pos, flags = sread_ui16 s pos in
- let pos, name = read_sstring_idx ctx pos in
- let pos, event_type = sread_from_table ctx false ITypeDefOrRef s pos in
- e.e_flags <- event_flags_of_int flags;
- e.e_name <- name;
- (* print_endline name; *)
- e.e_event_type <- event_type;
- add_relation ctx event_type (Event e);
- pos, Event e
- | PropertyMap pm ->
- let startpos = pos in
- let pos, parent = sread_from_table ctx false ITypeDef s pos in
- let offset = pos - startpos in
- let pos, property_list = ctx.table_sizes.(int_of_table IProperty) s pos in
- pm.pm_parent <- get_type_def parent;
- pm.pm_property_list <- List.rev_map get_property (read_list ctx IProperty IPropertyPtr property_list offset last pos);
- add_relation ctx parent (PropertyMap pm);
- pos, PropertyMap pm
- | PropertyPtr pp ->
- let pos, property = sread_from_table ctx false IProperty s pos in
- pp.prp_property <- get_property property;
- pos, PropertyPtr pp
- | Property prop ->
- let pos, flags = sread_ui16 s pos in
- let pos, name = read_sstring_idx ctx pos in
- let pos, t = read_field_ilsig_idx ~force_field:false ctx pos in
- prop.prop_flags <- property_flags_of_int flags;
- prop.prop_name <- name;
- (* print_endline name; *)
- prop.prop_type <- t;
- (* print_endline (ilsig_s t); *)
- pos, Property prop
- | MethodSemantics ms ->
- let pos, semantic = sread_ui16 s pos in
- let pos, m = sread_from_table ctx false IMethod s pos in
- let pos, association = sread_from_table ctx false IHasSemantics s pos in
- ms.ms_semantic <- semantic_flags_of_int semantic;
- ms.ms_method <- get_method m;
- ms.ms_association <- association;
- add_relation ctx m (MethodSemantics ms);
- add_relation ctx association (MethodSemantics ms);
- pos, MethodSemantics ms
- | MethodImpl mi ->
- let pos, cls = sread_from_table ctx false ITypeDef s pos in
- let pos, method_body = sread_from_table ctx false IMethodDefOrRef s pos in
- let pos, method_declaration = sread_from_table ctx false IMethodDefOrRef s pos in
- mi.mi_class <- get_type_def cls;
- mi.mi_method_body <- method_body;
- mi.mi_method_declaration <- method_declaration;
- add_relation ctx method_body (MethodImpl mi);
- pos, MethodImpl mi
- | ModuleRef modr ->
- let pos, name = read_sstring_idx ctx pos in
- modr.modr_name <- name;
- (* print_endline name; *)
- pos, ModuleRef modr
- | TypeSpec ts ->
- let pos, signature = read_ilsig_idx ctx pos in
- (* print_endline (ilsig_s signature); *)
- ts.ts_signature <- signature;
- pos, TypeSpec ts
- | ENCLog el ->
- let pos, token = sread_i32 s pos in
- let pos, func_code = sread_i32 s pos in
- el.el_token <- token;
- el.el_func_code <- func_code;
- pos, ENCLog el
- | ImplMap im ->
- let pos, flags = sread_ui16 s pos in
- let pos, forwarded = sread_from_table ctx false IMemberForwarded s pos in
- let pos, import_name = read_sstring_idx ctx pos in
- let pos, import_scope = sread_from_table ctx false IModuleRef s pos in
- im.im_flags <- impl_flags_of_int flags;
- im.im_forwarded <- forwarded;
- im.im_import_name <- import_name;
- im.im_import_scope <- get_module_ref import_scope;
- add_relation ctx forwarded (ImplMap im);
- pos, ImplMap im
- | ENCMap em ->
- let pos, token = sread_i32 s pos in
- em.encm_token <- token;
- pos, ENCMap em
- | FieldRVA f ->
- let pos, rva = sread_real_i32 s pos in
- let pos, field = sread_from_table ctx false IField s pos in
- f.fr_rva <- rva;
- f.fr_field <- get_field field;
- add_relation ctx field (FieldRVA f);
- pos, FieldRVA f
- | Assembly a ->
- let pos, hash_algo = sread_i32 s pos in
- let pos, major = sread_ui16 s pos in
- let pos, minor = sread_ui16 s pos in
- let pos, build = sread_ui16 s pos in
- let pos, rev = sread_ui16 s pos in
- let pos, flags = sread_i32 s pos in
- let pos, public_key = read_sblob_idx ctx pos in
- let pos, name = read_sstring_idx ctx pos in
- let pos, locale = read_sstring_idx ctx pos in
- a.a_hash_algo <- hash_algo_of_int hash_algo;
- a.a_major <- major;
- a.a_minor <- minor;
- a.a_build <- build;
- a.a_rev <- rev;
- a.a_flags <- assembly_flags_of_int flags;
- a.a_public_key <- public_key;
- a.a_name <- name;
- a.a_locale <- locale;
- pos, Assembly a
- | AssemblyProcessor ap ->
- let pos, processor = sread_i32 s pos in
- ap.ap_processor <- processor;
- pos, AssemblyProcessor ap
- | AssemblyOS aos ->
- let pos, platform_id = sread_i32 s pos in
- let pos, major = sread_i32 s pos in
- let pos, minor = sread_i32 s pos in
- aos.aos_platform_id <- platform_id;
- aos.aos_major_version <- major;
- aos.aos_minor_version <- minor;
- pos, AssemblyOS aos
- | AssemblyRef ar ->
- let pos, major = sread_ui16 s pos in
- let pos, minor = sread_ui16 s pos in
- let pos, build = sread_ui16 s pos in
- let pos, rev = sread_ui16 s pos in
- let pos, flags = sread_i32 s pos in
- let pos, public_key = read_sblob_idx ctx pos in
- let pos, name = read_sstring_idx ctx pos in
- let pos, locale = read_sstring_idx ctx pos in
- let pos, hash_value = read_sblob_idx ctx pos in
- ar.ar_major <- major;
- ar.ar_minor <- minor;
- ar.ar_build <- build;
- ar.ar_rev <- rev;
- ar.ar_flags <- assembly_flags_of_int flags;
- ar.ar_public_key <- public_key;
- ar.ar_name <- name;
- (* print_endline name; *)
- ar.ar_locale <- locale;
- (* print_endline locale; *)
- ar.ar_hash_value <- hash_value;
- pos, AssemblyRef ar
- | AssemblyRefProcessor arp ->
- let pos, processor = sread_i32 s pos in
- let pos, assembly_ref = sread_from_table ctx false IAssemblyRef s pos in
- arp.arp_processor <- processor;
- arp.arp_assembly_ref <- get_assembly_ref assembly_ref;
- pos, AssemblyRefProcessor arp
- | AssemblyRefOS aros ->
- let pos, platform_id = sread_i32 s pos in
- let pos, major = sread_i32 s pos in
- let pos, minor = sread_i32 s pos in
- let pos, assembly_ref = sread_from_table ctx false IAssemblyRef s pos in
- aros.aros_platform_id <- platform_id;
- aros.aros_major <- major;
- aros.aros_minor <- minor;
- aros.aros_assembly_ref <- get_assembly_ref assembly_ref;
- pos, AssemblyRefOS aros
- | File file ->
- let pos, flags = sread_i32 s pos in
- let pos, name = read_sstring_idx ctx pos in
- let pos, hash_value = read_sblob_idx ctx pos in
- file.file_flags <- file_flag_of_int flags;
- file.file_name <- name;
- (* print_endline ("file " ^ name); *)
- file.file_hash_value <- hash_value;
- pos, File file
- | ExportedType et ->
- let pos, flags = sread_i32 s pos in
- let pos, type_def_id = sread_i32 s pos in
- let pos, type_name = read_sstring_idx ctx pos in
- let pos, type_namespace = read_sstring_idx ctx pos in
- let pos, impl = sread_from_table ctx false IImplementation s pos in
- et.et_flags <- type_def_flags_of_int flags;
- et.et_type_def_id <- type_def_id;
- et.et_type_name <- type_name;
- et.et_type_namespace <- parse_ns type_namespace;
- et.et_implementation <- impl;
- add_relation ctx impl (ExportedType et);
- pos, ExportedType et
- | ManifestResource mr ->
- let pos, offset = sread_i32 s pos in
- let pos, flags = sread_i32 s pos in
- (* printf "offset 0x%x flags 0x%x\n" offset flags; *)
- let pos, name = read_sstring_idx ctx pos in
- let rpos, i = ctx.table_sizes.(int_of_table IImplementation) s pos in
- let pos, impl =
- if i = 0 then
- rpos, None
- else
- let pos, ret = sread_from_table ctx false IImplementation s pos in
- add_relation ctx ret (ManifestResource mr);
- pos, Some ret
- in
- mr.mr_offset <- offset;
- mr.mr_flags <- manifest_resource_flag_of_int flags;
- mr.mr_name <- name;
- mr.mr_implementation <- impl;
- pos, ManifestResource mr
- | NestedClass nc ->
- let pos, nested = sread_from_table ctx false ITypeDef s pos in
- let pos, enclosing = sread_from_table ctx false ITypeDef s pos in
- nc.nc_nested <- get_type_def nested;
- nc.nc_enclosing <- get_type_def enclosing;
- assert (nc.nc_nested.td_extra_enclosing = None);
- nc.nc_nested.td_extra_enclosing <- Some nc.nc_enclosing;
- add_relation ctx enclosing (NestedClass nc);
- pos, NestedClass nc
- | GenericParam gp ->
- let pos, number = sread_ui16 s pos in
- let pos, flags = sread_ui16 s pos in
- let pos, owner = sread_from_table ctx false ITypeOrMethodDef s pos in
- let spos, nidx =
- if ctx.strings_offset = 2 then
- sread_ui16 s pos
- else
- sread_i32 s pos
- in
- let pos, name =
- if nidx = 0 then
- spos, None
- else
- let pos, ret = read_sstring_idx ctx pos in
- (* print_endline ret; *)
- pos, Some ret
- in
- gp.gp_number <- number;
- gp.gp_flags <- generic_flags_of_int flags;
- gp.gp_owner <- owner;
- gp.gp_name <- name;
- add_relation ctx owner (GenericParam gp);
- pos, GenericParam gp
- | MethodSpec mspec ->
- let pos, meth = sread_from_table ctx false IMethodDefOrRef s pos in
- let pos, instantiation = read_method_ilsig_idx ctx pos in
- (* print_endline (ilsig_s instantiation); *)
- mspec.mspec_method <- meth;
- mspec.mspec_instantiation <- instantiation;
- add_relation ctx meth (MethodSpec mspec);
- pos, MethodSpec mspec
- | GenericParamConstraint gc ->
- let pos, owner = sread_from_table ctx false IGenericParam s pos in
- let pos, c = sread_from_table ctx false ITypeDefOrRef s pos in
- gc.gc_owner <- get_generic_param owner;
- gc.gc_constraint <- c;
- add_relation ctx owner (GenericParamConstraint gc);
- pos, GenericParamConstraint gc
- | _ -> assert false
- (* ******* META READING ********* *)
- let preset_sizes ctx rows =
- Array.iteri (fun n r -> match r with
- | false,_ -> ()
- | true,nrows ->
- (* printf "table %d nrows %d\n" n nrows; *)
- let tbl = table_of_int n in
- ctx.tables.(n) <- DynArray.init (nrows) (fun id -> mk_meta tbl (id+1))
- ) rows
- (* let read_ *)
- let read_meta ctx =
- (* read header *)
- let s = ctx.meta_stream in
- let pos = 4 + 1 + 1 in
- let flags = sget s pos in
- List.iter (fun i -> if flags land i = i then match i with
- | 0x01 ->
- ctx.strings_offset <- 4
- | 0x02 ->
- ctx.guid_offset <- 4
- | 0x04 ->
- ctx.blob_offset <- 4
- | 0x20 ->
- assert (not ctx.compressed);
- ctx.meta_edit_continue <- true
- | 0x80 ->
- assert (not ctx.compressed);
- ctx.meta_has_deleted <- true
- | _ -> assert false
- ) [0x01;0x02;0x04;0x20;0x80];
- let rid = sget s (pos+1) in
- ignore rid;
- let pos = pos + 2 in
- let mask = Array.init 8 ( fun n -> sget s (pos + n) ) in
- (* loop over masks and check which table is set *)
- let set_table = Array.init 64 (fun n ->
- let idx = n / 8 in
- let bit = n mod 8 in
- (mask.(idx) lsr bit) land 0x1 = 0x1
- ) in
- let pos = ref (pos + 8 + 8) in (* there is an extra 'sorted' field, which we do not use *)
- let rows = Array.mapi (fun i b -> match b with
- | false -> false,0
- | true ->
- let nidx, nrows = sread_i32 s !pos in
- if nrows > 0xFFFF then ctx.table_sizes.(i) <- sread_i32;
- pos := nidx;
- true,nrows
- ) set_table in
- set_coded_sizes ctx rows;
- (* pre-set all sizes *)
- preset_sizes ctx rows;
- Array.iteri (fun n r -> match r with
- | false,_ -> ()
- | true,nrows ->
- (* print_endline (string_of_int n); *)
- let fn = read_table_at ctx (table_of_int n) in
- let rec loop_fn n =
- if n = nrows then
- ()
- else begin
- let p, _ = fn n (n = (nrows-1)) !pos in
- pos := p;
- loop_fn (n+1)
- end
- in
- loop_fn 0
- ) rows;
- ()
- let read_padded i npad =
- let buf = Buffer.create 10 in
- let rec loop n =
- let chr = read i in
- if chr = '\x00' then begin
- let npad = n land 0x3 in
- if npad <> 0 then ignore (nread i (4 - npad));
- Buffer.contents buf
- end else begin
- Buffer.add_char buf chr;
- if n = npad then
- Buffer.contents buf
- else
- loop (n+1)
- end
- in
- loop 1
- let read_meta_tables pctx header module_cache =
- let i = pctx.r.i in
- seek_rva pctx (fst header.clr_meta);
- let magic = nread_string i 4 in
- if magic <> "BSJB" then error ("Error reading metadata table: Expected magic 'BSJB'. Got " ^ magic);
- let major = read_ui16 i in
- let minor = read_ui16 i in
- ignore major; ignore minor; (* no use for them *)
- ignore (read_i32 i); (* reserved *)
- let vlen = read_i32 i in
- let ver = nread i vlen in
- ignore ver;
- (* meta storage header *)
- ignore (read_ui16 i); (* reserved *)
- let nstreams = read_ui16 i in
- let rec streams n acc =
- let offset = read_i32 i in
- let size = read_real_i32 i in
- let name = read_padded i 32 in
- let acc = {
- str_offset = offset;
- str_size = size;
- str_name = name;
- } :: acc in
- if (n+1) = nstreams then
- acc
- else
- streams (n+1) acc
- in
- let streams = streams 0 [] in
- (* streams *)
- let compressed = ref None in
- let sstrings = ref "" in
- let sblob = ref "" in
- let sguid = ref "" in
- let sus = ref "" in
- let smeta = ref "" in
- let extra = ref [] in
- List.iter (fun s ->
- let rva = Int32.add (fst header.clr_meta) (Int32.of_int s.str_offset) in
- seek_rva pctx rva;
- match String.lowercase s.str_name with
- | "#guid" ->
- sguid := nread_string i (Int32.to_int s.str_size)
- | "#strings" ->
- sstrings := nread_string i (Int32.to_int s.str_size)
- | "#us" ->
- sus := nread_string i (Int32.to_int s.str_size)
- | "#blob" ->
- sblob := nread_string i (Int32.to_int s.str_size)
- | "#~" ->
- assert (Option.is_none !compressed);
- compressed := Some true;
- smeta := nread_string i (Int32.to_int s.str_size)
- | "#-" ->
- assert (Option.is_none !compressed);
- compressed := Some false;
- smeta := nread_string i (Int32.to_int s.str_size)
- | _ ->
- extra := s :: !extra
- ) streams;
- let compressed = match !compressed with
- | None -> error "No compressed or uncompressed metadata streams was found!"
- | Some c -> c
- in
- let tables = Array.init 64 (fun _ -> DynArray.create ()) in
- let ctx = {
- compressed = compressed;
- strings_stream = !sstrings;
- strings_offset = 2;
- blob_stream = !sblob;
- blob_offset = 2;
- guid_stream = !sguid;
- guid_offset = 2;
- us_stream = !sus;
- meta_stream = !smeta;
- meta_edit_continue = false;
- meta_has_deleted = false;
- module_cache = module_cache;
- extra_streams = !extra;
- relations = Hashtbl.create 64;
- typedefs = Hashtbl.create 64;
- tables = tables;
- table_sizes = Array.make (max_clr_meta_idx+1) sread_ui16;
- delays = [];
- } in
- read_meta ctx;
- let delays = ctx.delays in
- ctx.delays <- [];
- List.iter (fun fn -> fn()) delays;
- assert (ctx.delays = []);
- {
- il_tables = ctx.tables;
- il_relations = ctx.relations;
- il_typedefs = ctx.typedefs;
- }
|