diff --git a/ivette/src/frama-c/plugins/eva/api/general/index.ts b/ivette/src/frama-c/plugins/eva/api/general/index.ts index 55d8b6b7768e3e1717a91f126b192ce459c819bd..9d3579ba0b302412089088a1a7e96d56ea3a0c79 100644 --- a/ivette/src/frama-c/plugins/eva/api/general/index.ts +++ b/ivette/src/frama-c/plugins/eva/api/general/index.ts @@ -580,4 +580,26 @@ export const functionStats: State.Array< functionStatsData > = functionStats_internal; +const getStates_internal: Server.GetRequest< + marker, + [ string, string, string ][] + > = { + kind: Server.RqKind.GET, + name: 'plugins.eva.general.getStates', + input: jMarker, + output: Json.jList( + Json.jTry( + Json.jTriple( + Json.jFail(Json.jString,'String expected'), + Json.jFail(Json.jString,'String expected'), + Json.jFail(Json.jString,'String expected'), + ))), + signals: [], +}; +/** Get the domain states about the given marker */ +export const getStates: Server.GetRequest< + marker, + [ string, string, string ][] + >= getStates_internal; + /* ------------------------------------- */ diff --git a/src/plugins/value/api/general_requests.ml b/src/plugins/value/api/general_requests.ml index 8a6068698cb4dc5568e7d35a761ccc781bc291a9..0a981edd2760bf3fd68aaca570a94593e553945a 100644 --- a/src/plugins/value/api/general_requests.ml +++ b/src/plugins/value/api/general_requests.ml @@ -261,7 +261,7 @@ let _array = model -(* ----- Analysis statistics -------------------------------------------- *) +(* ----- Analysis statistics ------------------------------------------------ *) module AlarmCategory = struct open Server.Data @@ -470,4 +470,71 @@ let _array = model -(**************************************************************************) +(* ----- Domains states ----------------------------------------------------- *) + +let compute_lval_deps request lval = + let zone = Results.lval_deps lval request in + Locations.Zone.get_bases zone + +let compute_expr_deps request expr = + let zone = Results.expr_deps expr request in + Locations.Zone.get_bases zone + +let compute_instr_deps request = function + | Set (lval, expr, _) -> + Base.SetLattice.join + (compute_lval_deps request lval) + (compute_expr_deps request expr) + | Local_init (vi, AssignInit (SingleInit expr), _) -> + Base.SetLattice.join + (Base.SetLattice.inject_singleton (Base.of_varinfo vi)) + (compute_expr_deps request expr) + | _ -> Base.SetLattice.empty + +let compute_stmt_deps request stmt = + match stmt.skind with + | Instr (instr) -> compute_instr_deps request instr + | If (expr, _, _, _) -> compute_expr_deps request expr + | _ -> Base.SetLattice.empty + +let compute_marker_deps request = function + | Printer_tag.PStmt (_, stmt) + | PStmtStart (_, stmt) -> compute_stmt_deps request stmt + | PLval (_, _, lval) -> compute_lval_deps request lval + | PExp (_, _, expr) -> compute_expr_deps request expr + | PVDecl (_, _, vi) -> Base.SetLattice.inject_singleton (Base.of_varinfo vi) + | _ -> Base.SetLattice.empty + +let get_filtered_state request marker = + let bases = compute_marker_deps request marker in + match bases with + | Base.SetLattice.Top -> Results.print_states request + | Base.SetLattice.Set bases -> + if Base.Hptset.is_empty bases + then [] + else Results.print_states ~filter:bases request + +let get_states marker = + let kinstr = Printer_tag.ki_of_localizable marker in + match kinstr with + | Kglobal -> [] + | Kstmt stmt -> + let states_before = get_filtered_state (Results.before stmt) marker in + let states_after = get_filtered_state (Results.after stmt) marker in + match states_before, states_after with + | [], _ -> List.map (fun (name, after) -> name, "", after) states_after + | _, [] -> List.map (fun (name, before) -> name, before, "") states_before + | _, _ -> + let join (name, before) (name', after) = + assert (name = name'); + name, before, after + in + List.rev_map2 join states_before states_after + +let () = Request.register ~package + ~kind:`GET ~name:"getStates" + ~descr:(Markdown.plain "Get the domain states about the given marker") + ~input:(module Kernel_ast.Marker) + ~output:(module Data.Jlist + (Data.Jtriple (Data.Jstring) (Data.Jstring) (Data.Jstring))) + get_states diff --git a/src/plugins/value/utils/results.ml b/src/plugins/value/utils/results.ml index 540bc32142af6c42de9b85c1dbca17bc36ab2504..56935b6b2281b2aaef1ea25d1ccc65ad6624b27c 100644 --- a/src/plugins/value/utils/results.ml +++ b/src/plugins/value/utils/results.ml @@ -293,6 +293,26 @@ struct | Some extract -> convert (Response.map_join extract Cvalue.Model.join (get req)) + let print_states ?filter req = + let state = Response.map_join (fun x -> x) A.Dom.join (get req) in + let print (type s) + (key: s Abstract.Domain.key) + (module Domain: Abstract_domain.S with type state = s) + (state: s) acc = + let name = Structure.Key_Domain.name key in + let state = + match filter with + | None -> state + | Some bases -> Domain.filter `Print bases state + in + let str = Format.asprintf "%a" Domain.pretty state in + (name, str) :: acc + in + let polymorphic_fold_fun = A.Dom.{ fold = print } in + match state with + | `Top | `Bottom -> [] + | `Value state -> A.Dom.fold polymorphic_fold_fun state [] + (* Evaluation *) let eval_lval lval req = @@ -487,6 +507,10 @@ let get_cvalue_model req = | Error Bottom -> Cvalue.Model.bottom | Error (Top | DisabledDomain) -> Cvalue.Model.top +let print_states ?filter req = + let module E = Make () in + E.print_states ?filter req + (* Depedencies *) diff --git a/src/plugins/value/utils/results.mli b/src/plugins/value/utils/results.mli index e6c0678569aa2f5e7077e6780f285ac667560a5f..e18f41a032527bbde86a2c4b4122423e202afb9d 100644 --- a/src/plugins/value/utils/results.mli +++ b/src/plugins/value/utils/results.mli @@ -161,6 +161,11 @@ val get_cvalue_model : request -> Cvalue.Model.t (** Returns the Cvalue model. *) val get_cvalue_model_result : request -> Cvalue.Model.t result +(** Returns a textual representation of the internal domain states for the given + request. If [filter] is provided, states are filtered on the given bases + (for domains that support this feature). + Returns a list of pair (name, state) for all available domains. *) +val print_states: ?filter:Base.Hptset.t -> request -> (string * string) list (** Dependencies *)