You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

286 lines
10 KiB

(*
* Copyright (c) 2009 - 2013 Monoidics ltd.
* Copyright (c) 2013 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
(** Specifications and spec table *)
(** {2 Spec Tables} *)
(** Module for joined props: the result of joining together propositions repeatedly *)
module Jprop : sig
(** Remember when a prop is obtained as the join of two other props; the first parameter is an id *)
type 'a t =
| Prop of int * 'a Prop.t
| Joined of int * 'a Prop.t * 'a t * 'a t
(** Comparison for joined_prop *)
val compare : 'a t -> 'a t -> int
(** Dump the toplevel prop *)
val d_shallow : Prop.normal t -> unit
(** dump a joined prop list, the boolean indicates whether to print toplevel props only *)
val d_list : bool -> Prop.normal t list -> unit
(** Return true if the two join_prop's are equal *)
val equal : 'a t -> 'a t -> bool
(** Add fav to a jprop *)
val fav_add : Sil.fav -> 'a t -> unit
(** [jprop_filter filter joinedprops] applies [filter] to the elements
of [joindeprops] and applies it to the subparts if the result is
[None]. Returns the most absract results which pass [filter]. *)
val filter : ('a t -> 'b option) -> 'a t list -> 'b list
(** apply a substitution to a jprop *)
val jprop_sub : Sil.subst -> Prop.normal t -> Prop.exposed t
(** map the function to each prop in the jprop, pointwise *)
val map : ('a Prop.t -> 'b Prop.t) -> 'a t -> 'b t
(** Print a list of joined props, the boolean indicates whether to print subcomponents of joined props *)
val pp_list : printenv -> bool -> Format.formatter -> Prop.normal t list -> unit
(** Print the toplevel prop *)
val pp_short : printenv -> Format.formatter -> Prop.normal t -> unit
(** Extract the number associated to the toplevel jprop of a prop *)
val to_number : 'a t -> int
(** Extract the toplevel jprop of a prop *)
val to_prop : 'a t -> 'a Prop.t
end
(** set of visited nodes: node id and list of lines of all the instructions *)
module Visitedset : Set.S with type elt = int * int list
(** convert a Visitedset to a string *)
val visited_str : Visitedset.t -> string
(** A spec consists of:
pre: a joined prop
posts: a list of props with path
visited: a list of pairs (node_id, line) for the visited nodes *)
type 'a spec = { pre: 'a Jprop.t; posts: ('a Prop.t * Paths.Path.t) list; visited : Visitedset.t }
module NormSpec : sig (* encapsulate type for normalized specs *)
type t
end
module CallStats : (** module for tracing stats of function calls *)
sig
type t
type call_result = (** kind of result of a procedure call *)
| CR_success (** successful call *)
| CR_not_met (** precondition not met *)
| CR_not_found (** the callee has no specs *)
| CR_skip (** the callee was skipped *)
(** trace of an occurrence of function call *)
type trace = (call_result * bool) list
(** iterate over results of procedure calls *)
val iter : (Procname.t * Location.t -> trace -> unit) -> t -> unit
(** trace a procedure call *)
val trace : t -> Procname.t -> Location.t -> call_result -> bool -> unit
(** pretty print a call trace *)
val pp_trace : Format.formatter -> trace -> unit
end
(** Execution statistics *)
type stats =
{ stats_time: float; (** Analysis time for the procedure *)
stats_failure: failure_kind option; (** what type of failure stopped the analysis (if any) *)
stats_calls: Cg.in_out_calls; (** num of procs calling, and called *)
symops: int; (** Number of SymOp's throughout the whole analysis of the function *)
mutable nodes_visited_fp : IntSet.t; (** Nodes visited during the footprint phase *)
mutable nodes_visited_re : IntSet.t; (** Nodes visited during the re-execution phase *)
call_stats : CallStats.t;
}
type status = ACTIVE | INACTIVE | STALE
type phase = FOOTPRINT | RE_EXECUTION
type dependency_map_t = int Procname.Map.t
(** Type for calls consiting in the name of the callee and the location of the call *)
type call = Procname.t * Location.t
(** Collection of first step calls toward expensive call stacks or call stack allocating memory *)
type call_summary = {
expensive_calls: call list;
allocations: call list
}
(** Payload: results of some analysis *)
type payload =
{
preposts : NormSpec.t list option; (** list of specs *)
typestate : unit TypeState.t option; (** final typestate *)
calls: call_summary option; (** list of calls of the form (call, loc) *)
}
(** Procedure summary *)
type summary =
{ dependency_map: dependency_map_t; (** maps children procs to timestamp as last seen at the start of an analysys phase for this proc *)
nodes: int list; (** ids of cfg nodes of the procedure *)
phase: phase; (** in FOOTPRINT phase or in RE_EXECUTION PHASE *)
payload: payload; (** payload containing the result of some analysis *)
sessions: int ref; (** Session number: how many nodes went trough symbolic execution *)
stats: stats; (** statistics: execution time and list of errors *)
status: status; (** ACTIVE when the proc is being analyzed *)
timestamp: int; (** Timestamp of the specs, >= 0, increased every time the specs change *)
attributes : ProcAttributes.t; (** Attributes of the procedure *)
}
(** origin of a summary: current results dir, a spec library, or models *)
type origin =
| Res_dir
| Spec_lib
| Models
(** Add the summary to the table for the given function *)
val add_summary : Procname.t -> summary -> unit
(** Check if a summary for a given procedure exists in the models directory *)
val summary_exists_in_models : Procname.t -> bool
(** remove all the elements from the spec table *)
val clear_spec_tbl : unit -> unit
(** Dump a spec *)
val d_spec : 'a spec -> unit
(** Get the procedure name *)
val get_proc_name : summary -> Procname.t
(** Get the attributes of the procedure. *)
val get_attributes : summary -> ProcAttributes.t
(** Get the return type of the procedure *)
val get_ret_type : summary -> Sil.typ
(** Get the formal paramters of the procedure *)
val get_formals : summary -> (Mangled.t * Sil.typ) list
(** Get the flag with the given key for the procedure, if any *)
val get_flag : Procname.t -> string -> string option
(** Return the current phase for the proc *)
val get_phase : Procname.t -> phase
(** Return the origin of the spec file *)
val get_origin: Procname.t -> origin
(** Return the signature of a procedure declaration as a string *)
val get_signature : summary -> string
(** Return the specs for the proc in the spec table *)
val get_specs : Procname.t -> Prop.normal spec list
(** Return the specs and formal parameters for the proc in the spec table *)
val get_specs_formals : Procname.t -> Prop.normal spec list * (Mangled.t * Sil.typ) list
(** Get the specs from the payload of the summary. *)
val get_specs_from_payload : summary -> Prop.normal spec list
(** Return the summary option for the procedure name *)
val get_summary : Procname.t -> summary option
(** @deprecated Return the summary for the procedure name. Raises an exception when not found. *)
val get_summary_unsafe : string -> Procname.t -> summary
(** Return the current timestamp for the summary *)
val get_timestamp : summary -> int
(** Return the status (active v.s. inactive) of a procedure summary *)
val get_status : summary -> status
(** Check if the procedure is active *)
val is_active : Procname.t -> bool
(** Check if the procedure is active *)
val is_inactive : Procname.t -> bool
(** Initialize the summary for [proc_name] given dependent procs in list [depend_list].
Do nothing if a summary exists already. *)
val init_summary :
(Procname.t list * (** depend list *)
int list * (** nodes *)
proc_flags * (** procedure flags *)
(Procname.t * Location.t) list * (** calls *)
(Cg.in_out_calls option) * (** in and out calls *)
ProcAttributes.t) (** attributes of the procedure *)
-> unit
(** Reset a summary rebuilding the dependents and preserving the proc attributes if present. *)
val reset_summary : Cg.t -> Procname.t -> ProcAttributes.t option -> unit
(** Load procedure summary from the given file *)
val load_summary : DB.filename -> summary option
(** Check if a procedure summary exists for the given procedure name *)
val summary_exists : Procname.t -> bool
(** Cast a list of normalized specs to a list of specs *)
val normalized_specs_to_specs : NormSpec.t list -> Prop.normal spec list
(** Print the spec *)
val pp_spec : printenv -> (int * int) option -> Format.formatter -> Prop.normal spec -> unit
(** Print the spec table, the bool indicates whether to print whole seconds only *)
val pp_spec_table : printenv -> bool -> Format.formatter -> unit -> unit
(** Print the specs *)
val pp_specs : printenv -> Format.formatter -> Prop.normal spec list -> unit
(** Print the summary, the bool indicates whether to print whole seconds only *)
val pp_summary : printenv -> bool -> Format.formatter -> summary -> unit
(** Like proc_resolve_attributes but start from a proc_desc. *)
val pdesc_resolve_attributes : Cfg.Procdesc.t -> ProcAttributes.t
(** Try to find the attributes for a defined proc.
First look at specs (to get attributes computed by analysis)
then look at the attributes table.
If no attributes can be found, return None.
*)
val proc_resolve_attributes : Procname.t -> ProcAttributes.t option
(** Check if the procedure is from a library:
It's not defined, and there is no spec file for it. *)
val proc_is_library : ProcAttributes.t -> bool
(** Re-initialize a dependency map *)
val re_initialize_dependency_map : dependency_map_t -> dependency_map_t
(** Set the current status for the proc *)
val set_status : Procname.t -> status -> unit
(** Convert spec into normal form w.r.t. variable renaming *)
val spec_normalize : Prop.normal spec -> NormSpec.t
(** path to the .specs file for the given procedure in the current results dir *)
val res_dir_specs_filename : Procname.t -> DB.filename
(** Save summary for the procedure into the spec database *)
val store_summary : Procname.t -> summary -> unit
(** Return a compact representation of the summary *)
val summary_compact : Sil.sharing_env -> summary -> summary
(** Update the dependency map of [proc_name] with the current
timestamps of the dependents *)
val update_dependency_map : Procname.t -> unit