package mopsa

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file runner.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
(****************************************************************************)
(*                                                                          *)
(* This file is part of MOPSA, a Modular Open Platform for Static Analysis. *)
(*                                                                          *)
(* Copyright (C) 2017-2019 The MOPSA Project.                               *)
(*                                                                          *)
(* This program is free software: you can redistribute it and/or modify     *)
(* it under the terms of the GNU Lesser General Public License as published *)
(* by the Free Software Foundation, either version 3 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 Lesser General Public License for more details.                      *)
(*                                                                          *)
(* You should have received a copy of the GNU Lesser General Public License *)
(* along with this program.  If not, see <http://www.gnu.org/licenses/>.    *)
(*                                                                          *)
(****************************************************************************)

(** Runner - main entry point of the analysis *)

open Mopsa_utils
open Core.All
open Params.Options

let () = Sys.catch_break true

 (** {2 Command-line options} *)
(** ************************ *)

let opt_interactive = ref "automatic"

let () =
  register_builtin_option {
    key = "-engine";
    category = "Debugging";
    doc = "selects analysis mode";
    spec =  Symbol (
         ["automatic"; "interactive"; "dap"],
        (fun s ->
           match s with
           | "automatic" -> opt_interactive := "automatic"
           | "interactive" -> opt_interactive := "interactive"
           | "dap" -> opt_interactive := "dap"
           | _ -> ()
        )
      );
    default = "automatic";
  }

(** Parse command line arguments and apply [f] on the list of target
   source files *)
let parse_options passed_args f () =
  let files = ref [] in
  let args  = ref None in
  try
    Arg.parse_argv passed_args
    (ArgExt.argext_to_arg_list (Params.Options.get_options ()))
               (fun filename -> files := filename :: !files)
               "Modular Open Platform for Static Analysis";
    f !files !args
  with Stdlib.Arg.Bad f ->
    Params.Options.help (); 2


(** {2 Parsing} *)
(** *********** *)

(** Call the appropriate frontend to parse the input sources *)
let parse_program lang files =
  let front =
    try find_language_frontend lang
    with Not_found -> Exceptions.panic "No front-end found for language %s" lang
  in
  front.parse files



(** {2 Entry points} *)
(** **************** *)

let analyze_files (files:string list) (args:string list option) : int =
  let t = Timing.start () in
  try
    let config = Params.Paths.resolve_config_file !Params.Config.Parser.opt_config in
    let abstraction = Params.Config.Parser.parse config in
    let domain = Params.Config.Builder.from_json abstraction.domain in

    let prog = parse_program abstraction.language files in

    (* Top layer analyzer *)
    let module Domain = (val domain) in
    let module Toplevel = Toplevel.Make(Domain) in
    let module Engine =
      (val
        match !opt_interactive with
        | "interactive"   ->
           let module E = Engines.Interactive.Engine.Make(Toplevel)(Engines.Interactive.Terminal.Make) in
           (module E)
        | "dap"   ->
           let module E = Engines.Interactive.Engine.Make(Toplevel)(Engines.Interactive.Dap.Make) in
           (module E)
        | "automatic" ->
          let module E = Engines.Automatic.Make(Toplevel) in
          (module E)
        | x -> Exceptions.panic "unknown engine '%s'" x
        : Engines.Engine_sig.ENGINE with type t = Domain.t
      )
    in

    begin try
      let flow = Engine.init prog in
      let stmt = mk_stmt (S_program (prog, args)) prog.prog_range in
      let res =
        try Engine.analyze stmt flow
        with Toplevel.SysBreak flow ->
          let () = Debug.warn "Early termination, hooks will yield partial information only" in
          let () = Hook.on_finish Engine.man flow in
          raise (Toplevel.SysBreak flow)
      in
      let t = Timing.stop t in
      Hook.on_finish Engine.man res;
      Output.Factory.report Engine.man res ~time:t ~files
    with Exit -> exit 1
       | e ->
         let t = try Timing.stop t with _ -> 0. in
         Output.Factory.panic ~btrace:(Printexc.get_backtrace()) e ~time:t ~files (fun () ->
             let front = find_language_frontend abstraction.language in 
             front.on_panic e files t)
  end
  with
  | Exit ->
    exit 1
  | e ->
    let t = try Timing.stop t with _ -> 0. in
    Output.Factory.panic ~btrace:(Printexc.get_backtrace()) e ~time:t ~files (fun () -> ())


let run () =
  exit @@ parse_options Sys.argv analyze_files ()
OCaml

Innovation. Community. Security.