Advertisement
AngraMainyu

Untitled

Jan 19th, 2014
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 6.19 KB | None | 0 0
  1. (* (c) Microsoft Corporation 2005-2006.   *)
  2.  
  3. open Microsoft.AbstractIL
  4. open Microsoft.AbstractIL.Internal
  5.  
  6. open Printf
  7. open Microsoft.AbstractIL.IL
  8. open Microsoft.AbstractIL.BoundIL
  9.  
  10. (*-------------------------------------------------------------------------
  11.  * Define an assembly loader.
  12.  *----------------------------------------------------------------------- *)
  13.  
  14. let includes = ref [Microsoft.AbstractIL.Internal.Support.clrInstallationDirectory(); "." ]
  15. let pdb_includes = ref []
  16.  
  17. let loader = AssemblyBinder.mk_assembly_binder (fun () -> !includes, !pdb_includes)
  18.  
  19. (*-------------------------------------------------------------------------
  20.  * The analysis: this analysis simply counts the number of times
  21.  * the constructor System.Object() is the target of a 'newobj'
  22.  * or 'call' instruction.
  23.  *----------------------------------------------------------------------- *)
  24.  
  25. let total = ref 0
  26. let count = ref 0
  27.  
  28. let do_typ mdscope ilty =
  29.   ignore (bind_typ loader mdscope ilty)
  30.  
  31. let do_fspec mdscope fspec =
  32.   ignore (bind_fspec loader mdscope fspec)
  33.  
  34. let do_mspec mdscope mspec =
  35.   let bmeth = bind_mspec loader mdscope mspec in
  36.  
  37.   (* Bind the argument and return types in the thing we just bound to, just for fun. *)
  38.   (* The bound method and its associated metadata might lie in a *)
  39.   (* different module so the resolution scope must be adjusted accoridingly. *)
  40.   (* The new scope is the scope of the bound method. *)
  41.   let mdscope' = mdscope_of_bmeth bmeth in
  42.  List.iter (fun param -> do_typ mdscope' param.paramType) (mdef_of_bmeth bmeth).mdParams;
  43.   do_typ mdscope' (mdef_of_bmeth bmeth).mdReturn.returnType;
  44.  
  45.  (* Count the total *)
  46.  incr total;
  47.  
  48.  (* Check if the bound method is the same as the constructor for System.Object *)
  49.  (* Note we rebind bmeth_Object_ctor on each call, which is very inefficient.  *)
  50.  (* If we loaded mscorlib once and for all at the start of the file we can *)
  51.  (* bind it at the top level. *)
  52.  let mspec_Object_ctor = mk_ctor_mspec_for_nongeneric_boxed_tref(mscorlib.tref_Object,[]) in
  53.  let bmeth_Object_ctor = bind_mspec loader mscorlib_mdscope mspec_Object_ctor in
  54.  if bmeth_eq bmeth bmeth_Object_ctor then
  55.    incr count;
  56.  
  57.  (* Rebind the enclosing type and any instantiation,just for fun. *)
  58.  (* The metadata for these is in the original module. *)
  59.  mspec.EnclosingType |> do_typ mdscope;
  60.  mspec.GenericArguments |> List.iter (do_typ mdscope)
  61.  
  62. let do_instr mdscope i =
  63.  match i with
  64.  | I_calli (_,mr,_) -> () (* TODO: callsig *)
  65.    
  66.  | I_call (_,mspec,_)
  67.  | I_callvirt (_,mspec,_)
  68.  | I_callconstraint (_,_,mspec,_)
  69.  | I_newobj (mspec,_)
  70.  | I_ldftn mspec  -> do_mspec mdscope mspec;
  71.    
  72.  | I_ldfld (_,_,fr)
  73.  | I_ldsfld (_,fr)
  74.  | I_ldsflda fr
  75.  | I_ldflda fr
  76.  | I_stfld (_,_,fr)
  77.  | I_stsfld (_,fr) -> do_fspec mdscope fr
  78.  
  79.  | I_castclass typ
  80.  | I_isinst typ
  81.  | I_initobj typ
  82.  | I_cpobj typ
  83.  | I_stobj (_,_,typ)
  84.  | I_ldobj (_,_,typ)
  85.  | I_box typ
  86.  | I_unbox typ
  87.  | I_unbox_any typ
  88.  | I_ldelem_any (_,typ)
  89.  | I_stelem_any (_,typ)
  90.  | I_newarr (_,typ)
  91.  | I_sizeof typ
  92.  | I_ldelema (_,_,typ) -> do_typ mdscope typ
  93.    
  94.  | x -> ()
  95. let rec do_code mdscope x =
  96.  match x with
  97.  | BasicBlock bb -> Array.iter (do_instr mdscope) bb.bblockInstrs
  98.  | GroupBlock (locs,l) -> List.iter (do_code mdscope) l
  99.  | TryBlock (tryb,seh) ->
  100.      do_code mdscope tryb;
  101.      begin match seh with
  102.      | FaultBlock b -> do_code mdscope b
  103.      | FinallyBlock b -> do_code mdscope b
  104.      | FilterCatchBlock clsl ->
  105.       List.iter
  106.            (fun (flt,ctch) ->
  107.           (match flt with
  108.           | CodeFilter fltcode -> do_code mdscope fltcode
  109.           | TypeFilter ty -> do_typ mdscope ty);
  110.           do_code mdscope ctch)
  111.         clsl
  112.      end
  113.  | RestrictBlock (ls,c) -> do_code mdscope c
  114.  
  115. let do_bmeth bmeth =
  116.  let mdscope = mdscope_of_bmeth bmeth in
  117.  let mdef = mdef_of_bmeth bmeth in
  118.  match dest_mbody mdef.mdBody with
  119.  | MethodBody_il il ->
  120.      do_code mdscope il.ilCode
  121.  | b -> ()
  122.  
  123. let do_btycon btycon =
  124.  let btyp = generalize_btycon btycon in
  125.  let td = tdef_of_btycon btycon in
  126.  List.iter (mk_generalized_bmeth btyp >> do_bmeth) (dest_mdefs td.tdMethodDefs)
  127.  
  128. let rec do_btycons_for_tdefs bmodul nesting tdefs =
  129.  List.iter (do_btycons_for_tdef bmodul nesting) (dest_tdefs tdefs)
  130. and do_btycons_for_tdef bmodul nesting tdef =
  131.  do_btycon (mk_btycon (bmodul,nesting,tdef));
  132.  do_btycons_for_tdefs bmodul (nesting @ [tdef]) tdef.tdNested
  133.  
  134. let do_bassem bassem =
  135.  let bmainmod = mainmod_of_bassem bassem in
  136.  do_btycons_for_tdefs bmainmod [] (modul_of_bmodul bmainmod).modulTypeDefs
  137.  
  138.  
  139. (*-------------------------------------------------------------------------
  140. * Do the analysis for each assembly
  141. *----------------------------------------------------------------------- *)
  142.  
  143. let per_assembly assem =
  144.  try
  145.    (* Bind the assembly name using the loader.  This will search the given paths. *)
  146.    let bassem = bind_assem loader assem in
  147.    (* Fetch the main module of the assembly and bind its contents.  *)
  148.    do_bassem bassem;
  149.    (* Print results *)
  150.    print_endline ("There are "^string_of_int !total^" call/newobj instructions.");
  151.    print_endline ("System.Object::.ctor() is the target of "^string_of_int !count^" of them.");
  152.  with
  153.  | MethodNotFound (bencl,(s,n)) ->
  154.      eprintf "No method found with name '%s' and arity '%d' in type %a.\n" s n output_any bencl;
  155.      exit 1
  156.  | TypeNotFound (a,m, info, nesting, tyname) ->
  157.      eprintf "The type %s could not be found in assembly/module %s when being referenced from assembly/module '%s'" (String.concat "." (nesting @ [tyname])) info a;
  158.      exit 1
  159.  | e -> (*F# rethrow(); F#*) raise e
  160.  
  161. (*-------------------------------------------------------------------------
  162. * Top level stuff
  163. *----------------------------------------------------------------------- *)
  164.  
  165. let usage = [("--include", Arg.String (fun s -> includes := !includes @ [s]), "include files");
  166.             ("--symbol-path", Arg.String (fun s -> pdb_includes := !pdb_includes @ [s]), "pdb include files"); ]
  167.  
  168. let _ =
  169.  try Arg.parse usage per_assembly "bindall <options> <assembly-name>"
  170.  with e -> Printf.eprintf "%s\n" (Printexc.to_string e); exit 1
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement