|
@@ -1,2403 +0,0 @@
|
|
|
-(*
|
|
|
- * 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 ->
|
|
|
- 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;
|
|
|
- }
|
|
|
-
|